434 lines
16 KiB
Markdown
434 lines
16 KiB
Markdown
# ExpiryIndicator
|
|
|
|
SPFx-1.4.1-Solution für moderne und klassische Listen und Dokumentbibliotheken in SharePoint Server Subscription Edition.
|
|
|
|
## Funktionen
|
|
|
|
- Farbliche Anzeige einer vorhandenen, frei wählbaren Ablaufdatumsspalte.
|
|
- Fallback-Berechnung aus einem konfigurierbaren Erstellungsfeld und `defaultLifetime`.
|
|
- Priorisierte Regeln mit eigener Laufzeit und eigenen Farbschwellen anhand vorhandener Feldwerte.
|
|
- Verschachtelte V2-Bedingungsgruppen mit den logischen Verknüpfungen `AND` und `OR`.
|
|
- Command-Bar-Befehl zum Verlängern eines oder mehrerer Elemente um ein Kalenderjahr.
|
|
- CSR/JSLink-Darstellung und Ribbon-Befehl für klassische SharePoint-Ansichten.
|
|
- Zentraler Site-Collection-Standard mit optionalen Subweb- und Listen-Ausnahmen.
|
|
|
|
Die Solution provisioniert ausdrücklich keine fachliche Ablaufdatumsspalte und keinen Content Type.
|
|
|
|
## Regelauswertung
|
|
|
|
`rules` werden von oben nach unten geprüft. Für jede Regel gilt:
|
|
|
|
1. Das konfigurierte interne Feld muss in der Liste/Bibliothek existieren.
|
|
2. Erst dann wird sein Wert geprüft.
|
|
3. Die erste Regel mit passendem `columnValue` bestimmt `lifeTime` und `columnRule`.
|
|
4. Wenn keine Regel passt oder keines der Regelfelder vorhanden ist, gilt der gesamte `default`-Block.
|
|
|
|
Beispiel der intern gespeicherten Gesamtstruktur (nicht vollständig in eines der JSON-Felder des Dialogs einfügen):
|
|
|
|
```json
|
|
{
|
|
"baseField": "Created",
|
|
"expiryField": "ExpiryDate",
|
|
"default": {
|
|
"lifeTime": { "value": 2, "unit": "years" },
|
|
"columnRule": [
|
|
{
|
|
"daysUntilExpiry": 0,
|
|
"operator": "lessOrEqual",
|
|
"backgroundColor": "#a4262c",
|
|
"textColor": "#ffffff",
|
|
"label": "Abgelaufen"
|
|
}
|
|
]
|
|
},
|
|
"rules": [
|
|
{
|
|
"columnName": "DataPrivacy",
|
|
"columnValue": "PersDat1",
|
|
"lifeTime": { "value": 1, "unit": "years" },
|
|
"columnRule": [
|
|
{
|
|
"daysUntilExpiry": 30,
|
|
"operator": "lessOrEqual",
|
|
"backgroundColor": "#ffaa44",
|
|
"textColor": "#000000",
|
|
"label": "Läuft bald ab"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
## Konfiguration über den Application Customizer
|
|
|
|
### Voraussetzungen
|
|
|
|
1. Die App muss in der betreffenden Site installiert sein.
|
|
2. Die Liste oder Bibliothek muss die moderne Oberfläche verwenden.
|
|
3. Der angemeldete Benutzer benötigt die SharePoint-Berechtigung `Listen verwalten`.
|
|
4. Das konfigurierte Ablaufdatumsfeld muss bereits vorhanden sein. Die Solution legt dieses Feld nicht an.
|
|
|
|
Der Einstellungsdialog wird ohne dauerhaftes Element in der Befehlsleiste durch den Application Customizer
|
|
bereitgestellt. Dazu an die URL einer modernen Listen- oder Bibliotheksansicht den Parameter
|
|
`expiryIndicatorSettings=1` anhängen:
|
|
|
|
```text
|
|
/Shared Documents/Forms/AllItems.aspx?expiryIndicatorSettings=1
|
|
```
|
|
|
|
Sind bereits andere Query-Parameter vorhanden, wird der Parameter mit `&expiryIndicatorSettings=1` ergänzt.
|
|
Nach dem Speichern wird der Parameter entfernt und die Ansicht mit der neuen Konfiguration geladen. Ohne den
|
|
Parameter bleibt der Application Customizer unsichtbar. Nur Benutzer mit `Listen verwalten` können den Dialog
|
|
öffnen und speichern.
|
|
|
|
### Interne Feldnamen ermitteln
|
|
|
|
Es müssen interne SharePoint-Feldnamen verwendet werden, nicht die angezeigten Spaltennamen.
|
|
|
|
1. **Listeneinstellungen** beziehungsweise **Bibliothekseinstellungen** öffnen.
|
|
2. Die gewünschte Spalte anklicken.
|
|
3. In der URL den Wert hinter `Field=` ablesen.
|
|
|
|
Beispiel: Bei `...FldEdit.aspx?Field=DataPrivacy` lautet der interne Feldname `DataPrivacy`.
|
|
Ein Anzeigename wie "Ablaufdatum" kann intern beispielsweise `ExpiryDate` oder
|
|
`CustomerExpiryDate` heißen.
|
|
|
|
### Allgemeine Einstellungen
|
|
|
|
- **Internes Basis-Datumsfeld:** Ausgangsdatum für die Berechnung, normalerweise `Created`.
|
|
- **Internes Ablaufdatumsfeld:** Vorhandenes Datumsfeld, beispielsweise `ExpiryDate`.
|
|
- **Standardlaufzeit:** Zahl für die Laufzeit, beispielsweise `2`.
|
|
- **Einheit:** `days`, `months` oder `years`.
|
|
- **Verlängerung vorher bestätigen:** Zeigt vor der Verlängerung eine Sicherheitsabfrage.
|
|
- **Text bei fehlendem Datum:** Wird angezeigt, wenn weder Basis- noch Ablaufdatum gelesen werden können.
|
|
|
|
Ist das Ablaufdatumsfeld eines Elements bereits gefüllt, wird dieser gespeicherte Wert verwendet.
|
|
Nur bei einem leeren Ablaufdatumsfeld wird das Datum aus Basisdatum plus passender Laufzeit berechnet.
|
|
Ein berechnetes Datum wird durch die Anzeige allein nicht in das SharePoint-Feld geschrieben.
|
|
|
|
### Standard-Farbregeln
|
|
|
|
In **Standard-Farbregeln** wird nur das JSON-Array für `default.columnRule` eingetragen:
|
|
|
|
```json
|
|
[
|
|
{
|
|
"daysUntilExpiry": 0,
|
|
"operator": "lessOrEqual",
|
|
"backgroundColor": "#a4262c",
|
|
"textColor": "#ffffff",
|
|
"label": "Abgelaufen"
|
|
},
|
|
{
|
|
"daysUntilExpiry": 30,
|
|
"operator": "lessOrEqual",
|
|
"backgroundColor": "#ffaa44",
|
|
"textColor": "#000000",
|
|
"label": "Läuft bald ab"
|
|
},
|
|
{
|
|
"daysUntilExpiry": 90,
|
|
"operator": "lessOrEqual",
|
|
"backgroundColor": "#fff4ce",
|
|
"textColor": "#000000",
|
|
"label": "Beobachten"
|
|
}
|
|
]
|
|
```
|
|
|
|
Die Farbregeln werden von oben nach unten ausgewertet; die erste passende Regel gewinnt. Deshalb muss
|
|
`<= 0` vor `<= 30` und `<= 90` stehen. Ohne passende Farbregel wird das Datum ohne besondere Farbe angezeigt.
|
|
Eine passende Regel färbt die komplette SharePoint-Zeile mit einem durchgehenden Verlauf vom weißen
|
|
SharePoint-Standardhintergrund links bis zur konfigurierten `backgroundColor` rechts. Die Auswahlspalte bleibt
|
|
ungefärbt. `textColor` bestimmt die Schriftfarbe der eingefärbten Zellen. Ein konfiguriertes `label` wird in
|
|
derselben SharePoint-Standardschrift direkt neben dem Datum dargestellt.
|
|
|
|
Unterstützte Operatoren:
|
|
|
|
| Operator | Bedeutung |
|
|
| --- | --- |
|
|
| `lessThan` | Resttage kleiner als Grenzwert |
|
|
| `lessOrEqual` | Resttage kleiner oder gleich Grenzwert |
|
|
| `equal` | Resttage genau gleich Grenzwert |
|
|
| `greaterOrEqual` | Resttage größer oder gleich Grenzwert |
|
|
| `greaterThan` | Resttage größer als Grenzwert |
|
|
|
|
### Feldabhängige Regeln
|
|
|
|
In **Feldwertregeln** wird nur das JSON-Array für `rules` eingetragen. Folgendes Beispiel verwendet bei
|
|
`DataPrivacy = PersDat1` eine Laufzeit von einem Jahr und bei `PersDat2` eine Laufzeit von drei Jahren:
|
|
|
|
```json
|
|
[
|
|
{
|
|
"columnName": "DataPrivacy",
|
|
"columnValue": "PersDat1",
|
|
"lifeTime": {
|
|
"value": 1,
|
|
"unit": "years"
|
|
},
|
|
"columnRule": [
|
|
{
|
|
"daysUntilExpiry": 0,
|
|
"operator": "lessOrEqual",
|
|
"backgroundColor": "#a4262c",
|
|
"textColor": "#ffffff",
|
|
"label": "Abgelaufen"
|
|
},
|
|
{
|
|
"daysUntilExpiry": 30,
|
|
"operator": "lessOrEqual",
|
|
"backgroundColor": "#ffaa44",
|
|
"textColor": "#000000",
|
|
"label": "Läuft bald ab"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"columnName": "DataPrivacy",
|
|
"columnValue": "PersDat2",
|
|
"lifeTime": {
|
|
"value": 3,
|
|
"unit": "years"
|
|
},
|
|
"columnRule": [
|
|
{
|
|
"daysUntilExpiry": 0,
|
|
"operator": "lessOrEqual",
|
|
"backgroundColor": "#a4262c",
|
|
"textColor": "#ffffff",
|
|
"label": "Abgelaufen"
|
|
},
|
|
{
|
|
"daysUntilExpiry": 60,
|
|
"operator": "lessOrEqual",
|
|
"backgroundColor": "#ffaa44",
|
|
"textColor": "#000000",
|
|
"label": "Läuft bald ab"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
```
|
|
|
|
Das bisherige Format mit `columnName` und `columnValue` bleibt in Version 2.0 vollständig kompatibel.
|
|
|
|
### Verkettete Regeln mit AND und OR (Version 2.0)
|
|
|
|
Neue Regeln verwenden `condition`. Eine Gruppe enthält `operator` mit `and` oder `or` sowie ein Array
|
|
`conditions`. Jeder Eintrag ist entweder eine Feldbedingung oder eine weitere Gruppe. Dieses Beispiel gilt,
|
|
wenn `eGovPersDat` dem angegebenen Taxonomy-Term entspricht **und** der Status `Freigegeben` oder `Genehmigt` ist:
|
|
|
|
```json
|
|
[
|
|
{
|
|
"condition": {
|
|
"operator": "and",
|
|
"conditions": [
|
|
{
|
|
"columnName": "eGovPersDat",
|
|
"columnValue": "0d19386a-ebe1-4955-ad12-164d7846bca6"
|
|
},
|
|
{
|
|
"operator": "or",
|
|
"conditions": [
|
|
{
|
|
"columnName": "Status",
|
|
"columnValue": "Freigegeben"
|
|
},
|
|
{
|
|
"columnName": "Status",
|
|
"columnValue": "Genehmigt"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
},
|
|
"lifeTime": {
|
|
"value": 1,
|
|
"unit": "years"
|
|
},
|
|
"columnRule": [
|
|
{
|
|
"daysUntilExpiry": 0,
|
|
"operator": "lessOrEqual",
|
|
"backgroundColor": "#a4262c",
|
|
"textColor": "#ffffff",
|
|
"label": "Abgelaufen"
|
|
},
|
|
{
|
|
"daysUntilExpiry": 7,
|
|
"operator": "lessOrEqual",
|
|
"backgroundColor": "#ffaa44",
|
|
"textColor": "#000000",
|
|
"label": "Läuft bald ab"
|
|
},
|
|
{
|
|
"daysUntilExpiry": 14,
|
|
"operator": "lessOrEqual",
|
|
"backgroundColor": "#fff4ce",
|
|
"textColor": "#000000",
|
|
"label": "Beobachten"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
```
|
|
|
|
- `and`: Alle enthaltenen Bedingungen müssen erfüllt sein.
|
|
- `or`: Mindestens eine enthaltene Bedingung muss erfüllt sein.
|
|
- Ein fehlendes Feld erfüllt eine Feldbedingung nicht.
|
|
- Gruppen dürfen bis zu zehn Ebenen tief verschachtelt werden.
|
|
- Die erste vollständig passende fachliche Regel gewinnt; andernfalls gilt `default`.
|
|
- Der Einstellungsdialog lehnt ungültige oder leere Bedingungsgruppen vor dem Speichern ab.
|
|
|
|
Die Regeln werden von oben nach unten geprüft. Dabei gilt:
|
|
|
|
1. Existiert `columnName` in der Liste oder Bibliothek?
|
|
2. Entspricht der Feldwert dem konfigurierten `columnValue`?
|
|
3. Die erste passende Regel liefert Laufzeit und Farbregeln.
|
|
4. Existiert das Feld nicht oder passt kein Wert, werden Standardlaufzeit und Standard-Farbregeln verwendet.
|
|
|
|
Bei Managed-Metadata-Feldern sollte `columnValue` die Term-GUID enthalten. SharePoint Server liefert im
|
|
REST-Ergebnis teilweise die WssId anstelle der lesbaren Bezeichnung im Feld `Label`; die Term-GUID bleibt
|
|
dagegen stabil. Der Vergleich der GUID erfolgt ohne Beachtung der Groß-/Kleinschreibung. Beispiel:
|
|
|
|
```json
|
|
{
|
|
"columnName": "eGovPersDat",
|
|
"columnValue": "0d19386a-ebe1-4955-ad12-164d7846bca6",
|
|
"lifeTime": { "value": 1, "unit": "years" },
|
|
"columnRule": []
|
|
}
|
|
```
|
|
|
|
Nach **Speichern** wird die Konfiguration als JSON direkt in `ClientSideComponentProperties` des mit dem
|
|
ExpiryIndicator gebundenen lokalen Listenfeldes gespeichert. Damit verwendet die App denselben
|
|
Konfigurationsmechanismus wie andere SPFx-Extensions und benötigt keine zusätzliche Konfigurationsliste.
|
|
PortalSettings kann optional dieselben Component Properties verwalten, ist aber keine Voraussetzung für den
|
|
Betrieb des ExpiryIndicators.
|
|
|
|
### Zentrale Vererbung mit PortalSettings (Version 2.1)
|
|
|
|
Version 2.1 kann einen Standard aus dem Property Bag des Root Webs auf alle registrierten Bindungen der
|
|
Site Collection vererben. Die Aufloesung erfolgt in dieser Reihenfolge:
|
|
|
|
1. lokale Konfiguration am Listenfeld,
|
|
2. optionaler Override im Property Bag des aktuellen Subwebs,
|
|
3. Site-Collection-Standard im Property Bag des Root Webs,
|
|
4. eingebauter Standard der Extension.
|
|
|
|
`Enable-ExpiryIndicator.ps1` registriert jede Bindung im Root Web und verwendet fuer neue oder bisher leere
|
|
Feld-Properties eine schlanke Vererbungsreferenz. Bestehende vollstaendige Listenkonfigurationen bleiben beim
|
|
erneuten Ausfuehren des Skripts erhalten. In PortalSettings kann man den zentralen Standard bearbeiten, einzelne
|
|
Bindungen auswaehlen oder alle registrierten Bindungen bewusst auf Vererbung umstellen. Eine versteckte Liste
|
|
wird nicht verwendet.
|
|
|
|
Bei einem Upgrade wird eine vorhandene Konfiguration aus der früheren ausgeblendeten Liste
|
|
`_ExpiryIndicatorConfiguration` weiterhin gelesen, solange noch keine Component Properties gespeichert wurden.
|
|
Beim nächsten Speichern wird sie in das gebundene Feld übernommen. Die alte Liste wird aus Sicherheitsgründen
|
|
nicht automatisch gelöscht.
|
|
|
|
### Anzeige aktivieren
|
|
|
|
Der Field Customizer wird einmal pro Liste beziehungsweise Bibliothek mit dem mitgelieferten Skript
|
|
an der Ablaufdatumsspalte registriert:
|
|
|
|
```powershell
|
|
.\scripts\Enable-ExpiryIndicator.ps1 `
|
|
-SiteUrl 'https://sharepoint/sites/fachbereich' `
|
|
-ListTitle 'Dokumente' `
|
|
-ExpiryFieldInternalName 'CustomerExpiryDate'
|
|
```
|
|
|
|
Der Field Customizer und seine Component Properties werden am mit `ExpiryFieldInternalName` angegebenen lokalen
|
|
Listenfeld registriert. Der interne Name wird anschließend aus dieser Bindung ermittelt und im Einstellungsdialog
|
|
nur lesbar angezeigt. Das Command Set wird durch die Installation der App registriert. Danach die Listenansicht
|
|
neu laden.
|
|
|
|
### Klassische SharePoint-Ansichten
|
|
|
|
Version 2.1 legt bei der App-Installation `ExpiryIndicatorClassic.js` unter
|
|
`SiteAssets/ExpiryIndicator` ab. Das Aktivierungsskript registriert standardmäßig für die angegebene Liste:
|
|
|
|
- einen einmaligen Web-`ScriptLink` für CSR/JSLink, der das gebundene Feld der aktuellen Liste selbst erkennt,
|
|
- die Berechnung, Beschriftung und den Zeilenverlauf in der klassischen Ansicht,
|
|
- den Ribbon-Befehl **Ablaufdatum +1 Jahr**,
|
|
- den Einstellungsdialog über denselben URL-Parameter `expiryIndicatorSettings=1`.
|
|
|
|
Soll nur die moderne Ansicht aktiviert werden, kann die Classic-Registrierung ausgelassen werden:
|
|
|
|
```powershell
|
|
.\scripts\Enable-ExpiryIndicator.ps1 `
|
|
-SiteUrl 'https://sharepoint/sites/fachbereich' `
|
|
-ListTitle 'Dokumente' `
|
|
-ExpiryFieldInternalName 'CustomerExpiryDate' `
|
|
-SkipClassic
|
|
```
|
|
|
|
Die klassische Laufzeit verwendet dieselbe Vererbungskette und dieselben Feld-Properties wie die moderne
|
|
Laufzeit. Es gibt keine zweite Konfiguration.
|
|
|
|
### Ablaufdatum um ein Jahr verlängern
|
|
|
|
Ein oder mehrere Elemente markieren und **Ablaufdatum +1 Jahr** auswählen. Ist bereits ein Ablaufdatum
|
|
gespeichert, wird dieses um ein Kalenderjahr verlängert. Ist das Feld leer, wird zunächst das berechnete
|
|
Ablaufdatum verwendet, um ein Jahr verlängert und anschließend in das Ablaufdatumsfeld geschrieben.
|
|
|
|
Der Befehl ist nur sichtbar, wenn das konfigurierte Ablaufdatumsfeld existiert, mindestens ein Element
|
|
markiert wurde und der Benutzer Elemente bearbeiten darf.
|
|
|
|
## Build
|
|
|
|
SPFx 1.4.1 verwendet die Legacy-Toolchain. Unterstützt wird Node.js 6 oder 8; empfohlen wird für reproduzierbare Builds Node.js 8.17.0.
|
|
|
|
```powershell
|
|
npm install
|
|
npm run package
|
|
```
|
|
|
|
Das Paket wird als `sharepoint/solution/expiry-indicator.sppkg` erzeugt.
|
|
|
|
## Installation
|
|
|
|
1. `expiry-indicator.sppkg` in den App Catalog der On-Premises-Farm laden.
|
|
2. Die App in der gewünschten Site installieren.
|
|
3. Eine moderne oder klassische Liste/Bibliothek öffnen und wie im Abschnitt
|
|
**Konfiguration über den Application Customizer** beschrieben konfigurieren.
|
|
4. Den Field Customizer mit der vorhandenen Ablaufdatumsspalte verbinden:
|
|
|
|
```powershell
|
|
.\scripts\Enable-ExpiryIndicator.ps1 `
|
|
-SiteUrl 'https://sharepoint/sites/fachbereich' `
|
|
-ListTitle 'Dokumente' `
|
|
-ExpiryFieldInternalName 'CustomerExpiryDate'
|
|
```
|
|
|
|
Das Skript ist in einer SharePoint Management Shell beziehungsweise auf einem Rechner mit den passenden SharePoint-CSOM-Assemblies und Zugriff auf die Site auszuführen.
|
|
|
|
### Upgrade auf Version 2.1
|
|
|
|
1. Das vorhandene Paket im App Catalog durch Version `2.1.0.0` ersetzen.
|
|
2. Die App in der Site aktualisieren. Die enthaltene Feature-UpgradeAction provisioniert ausschließlich das
|
|
aktualisierten Assets und legt keine fachliche Spalte an.
|
|
3. `Enable-ExpiryIndicator.ps1` für jede bereits angebundene Liste erneut ausführen. Das Skript erhält die
|
|
vorhandene Feldkonfiguration und ergänzt idempotent den gemeinsamen Web-ScriptLink sowie die
|
|
listenspezifische Ribbon-Registrierung sowie das zentrale Bindungsinventar.
|
|
4. Modern- und Classic-Ansicht mit geleertem Browsercache neu laden und prüfen.
|
|
|
|
## Deaktivierung
|
|
|
|
```powershell
|
|
.\scripts\Disable-ExpiryIndicator.ps1 `
|
|
-SiteUrl 'https://sharepoint/sites/fachbereich' `
|
|
-ListTitle 'Dokumente' `
|
|
-ExpiryFieldInternalName 'CustomerExpiryDate'
|
|
```
|
|
|
|
Das Skript entfernt die Field-Customizer-Verknüpfung sowie die listenspezifische Classic-Ribbon-Registrierung.
|
|
Die Spalte und alle fachlichen Daten bleiben erhalten. Der gemeinsam auf Web-Ebene verwendete ScriptLink bleibt
|
|
standardmäßig bestehen, da ihn weitere Listen benötigen können. Wenn keine weitere Liste den ExpiryIndicator
|
|
verwendet, kann er mit `-RemoveClassicWebScriptLink` entfernt werden. Die modernen Command-Set- und
|
|
Application-Customizer-Registrierungen werden durch das Entfernen der App aus der Site beseitigt.
|