Server-Bibliothek
vor 18 Std. 98bce1b0da675715b2e5482c0ad61ba21135f62f
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
134
135
import { LitElement, html, nothing } from 'lit';
import { customElement, property } from 'lit/decorators.js';
import { event, type EventRef } from '@dh-software/lit-extensions';
import type { EintragMitBefund, LokalerZustand } from '../bruecke';
 
/** Was der jeweilige Zustand für den Nutzer bedeutet. */
const ZUSTAND_TEXT: Record<LokalerZustand, string> = {
  fehlt: 'nicht auf diesem Rechner',
  aktuell: 'aktuell',
  veraltet: 'veraltet',
  fremd: 'von Hand verändert',
};
 
const ZUSTAND_KLASSE: Record<LokalerZustand, string> = {
  fehlt: 'zustand-fehlt',
  aktuell: 'zustand-aktuell',
  veraltet: 'zustand-veraltet',
  fremd: 'zustand-fremd',
};
 
/**
 * Eine Zeile des Katalogs im Client. Anders als in der Weboberfläche steht hier,
 * was auf diesem Rechner liegt — das ist der ganze Unterschied.
 */
@customElement('client-zeile')
export class ClientZeile extends LitElement {
  @property({ attribute: false }) eintrag!: EintragMitBefund;
  @property({ type: Boolean }) laeuft = false;
 
  @event({ bubbles: true, composed: true }, 'holen')
  private holen!: EventRef<EintragMitBefund>;
 
  @event({ bubbles: true, composed: true }, 'verknuepfen')
  private verknuepfen!: EventRef<EintragMitBefund>;
 
  // Light DOM, damit das globale dh-components-Theme greift.
  createRenderRoot() {
    return this;
  }
 
  render() {
    const eintrag = this.eintrag;
    return html`
      <div class="zeile">
        <div class="zeile-info">
          <span class="zeile-name">
            ${eintrag.name}
            ${eintrag.einstufung === 'lizenzpflichtig'
              ? html`<span class="marke lizenz-marke">lizenzpflichtig</span>`
              : nothing}
            ${eintrag.einstufung === 'intern' ? html`<span class="marke intern-marke">intern</span>` : nothing}
          </span>
          <span class="zeile-meta">${this.rendereStand()}${this.rendereZustand()}</span>
          ${eintrag.hinweis ? html`<span class="zeile-hinweis">${eintrag.hinweis}</span>` : nothing}
        </div>
        <div class="zeile-aktionen">${this.rendereAktion()}${this.rendereVerknuepfung()}</div>
      </div>
    `;
  }
 
  private rendereStand() {
    const zeitpunkt = this.eintrag.veroeffentlichtAm || this.eintrag.dateiStandVom;
    if (!zeitpunkt) {
      return nothing;
    }
    const datum = new Date(zeitpunkt);
    if (Number.isNaN(datum.getTime())) {
      return nothing;
    }
    return html`Stand ${datum.toLocaleDateString('de-DE')}`;
  }
 
  /** Nur bei eigenständigen Programmen aussagekräftig — Installer verraten hier nichts. */
  private rendereZustand() {
    const befund = this.eintrag.lokal;
    if (!befund) {
      return nothing;
    }
    return html` &nbsp;·&nbsp;
      <span class=${ZUSTAND_KLASSE[befund.zustand]}>${ZUSTAND_TEXT[befund.zustand]}</span>`;
  }
 
  /**
   * Ein rundes Symbol wie in der Weboberfläche. Was der Klick bewirkt, steht
   * ohnehin schon als Zustand in der Zeile — die Beschriftung wäre eine
   * Wiederholung. Steht ein Update an, ist der Knopf gefüllt statt flach.
   */
  private rendereAktion() {
    const eintrag = this.eintrag;
    if (!eintrag.dateiname) {
      return html`<span class="zeile-hinweis">keine Datei hinterlegt</span>`;
    }
    const zustand = eintrag.lokal?.zustand;
    const stehtAn = zustand === 'veraltet' || zustand === 'fremd';
    const zweck = stehtAn ? 'aktualisieren' : zustand === 'aktuell' ? 'erneut holen' : 'holen';
    return html`<dh-button
      icon-button
      variant=${stehtAn ? 'filled' : 'standard'}
      title=${`${eintrag.name} ${zweck}`}
      ?disabled=${this.laeuft}
      @click=${this.beiHolen}
    >
      <span slot="img" class="fv-icon-download"></span>
    </dh-button>`;
  }
 
  private rendereVerknuepfung() {
    const befund = this.eintrag.lokal;
    if (!befund || befund.zustand === 'fehlt') {
      return nothing;
    }
    return html`<dh-button
      icon-button
      variant="standard"
      title="Verknüpfung auf dem Desktop anlegen"
      @click=${this.beiVerknuepfen}
    >
      <span slot="img" class="fv-icon-link"></span>
    </dh-button>`;
  }
 
  private beiHolen(): void {
    this.holen.dispatch(this.eintrag);
  }
 
  private beiVerknuepfen(): void {
    this.verknuepfen.dispatch(this.eintrag);
  }
}
 
declare global {
  interface HTMLElementTagNameMap {
    'client-zeile': ClientZeile;
  }
}