aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/src/meshbay_hub/static/group-name.js
blob: f0ace6a32d8be6a57b5d3d169548d1b33fdcda6e (plain) (blame)
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
import { html } from './vendor/htm-preact.js';
import { t } from './i18n.js';
import { sourceLabel } from './source-merge.js';

/**
 * A group's name with the `@owner` handle under it.
 *
 * Group names are unique only per owner account (the hub enforces that), so the
 * `@handle` is what tells two groups called "photos" apart. `owner` is the
 * owner's username for a local group, or the source hub for a federated one
 * (docs/MESHBAY_DESIGN.md §7.3); the caller decides which.
 *
 * `inline` renders "name@owner" on one line, for places that cannot take a
 * block — a badge, a `confirm()` string built elsewhere.
 */
export function GroupName({ name, owner, inline = false }) {
  if (inline) return owner ? `${name}@${owner}` : name;
  return html`
    <span class="gn">
      <span class="gn-name">${name}</span>
      ${owner && html`<span class="gn-owner">@${owner}</span>`}
    </span>
  `;
}

/**
 * Which group serves an entry, or how many groups have it.
 *
 * The Search view merges a file several groups share into one entry, so the
 * badge under a card cannot always name a group. One source keeps naming it
 * and keeps linking to it; more than one becomes a count, and *which* one was
 * picked is deliberately not shown (docs/MESHBAY_DESIGN.md §9.11).
 *
 * `entries` is the whole unit — every episode of a show, every track of an
 * album — not the entry the card was drawn from; `sourceLabel` explains why.
 * Renders nothing at all on the single-group Group page, where an entry
 * carries no group and there is only ever one source anyway.
 *
 * It lives here rather than in `source-merge.js` because that module is
 * executed standalone by its test and must keep importing nothing; and here
 * rather than in one of the three apps that need it, because a copy apiece is
 * three chances to disagree about what a merged card says.
 *
 * A `div` by default: the three card badges rely on `text-overflow: ellipsis`,
 * which does nothing on an inline box. `link` gives the flat row's inline
 * pill instead.
 */
export function SourceTag({ entries, cls, link = false }) {
  const { count, name, groupId } = sourceLabel(entries);
  if (count > 1) return html`<span class=${cls}>${t('search.n_sources', { n: count })}</span>`;
  if (!name) return null;
  if (link && groupId) {
    return html`<a href="#/group/${groupId}" class=${cls}
      onClick=${(e) => e.stopPropagation()}>${name}</a>`;
  }
  return html`<div class=${cls}>${name}</div>`;
}