Aktualisiere Versionsnummern auf 1.0.7 in package.json, package-solution.json, ExpiryIndicatorFieldCustomizer.manifest.json und ExpiryIndicatorCommandSet.manifest.json; verbessere die Darstellung der Ablaufdatumsspalte in ExpiryIndicatorFieldCustomizer.ts und aktualisiere die ToDo.md mit neuen Informationen zur Zeilenfärbung.

This commit is contained in:
Torsten Brendgen
2026-07-17 21:12:33 +02:00
parent 11229d87eb
commit 2f5baff82f
7 changed files with 57 additions and 16 deletions

View File

@@ -128,9 +128,9 @@ In **Standard-Farbregeln** wird nur das JSON-Array für `default.columnRule` ein
Die Farbregeln werden von oben nach unten ausgewertet; die erste passende Regel gewinnt. Deshalb muss 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. `<= 0` vor `<= 30` und `<= 90` stehen. Ohne passende Farbregel wird das Datum ohne besondere Farbe angezeigt.
Eine passende Regel färbt die komplette SharePoint-Zelle mit `backgroundColor` und passt ausschließlich die Eine passende Regel färbt die komplette SharePoint-Zeile einschließlich aller sichtbaren Zellen mit
Schriftfarbe über `textColor` an. `label` bleibt aus Kompatibilitätsgründen konfigurierbar, wird in der Liste `backgroundColor` und passt deren Schriftfarbe über `textColor` an. Ein konfiguriertes `label` wird in derselben
aber nicht zusätzlich neben dem Datum dargestellt. SharePoint-Standardschrift direkt neben dem Datum dargestellt.
Unterstützte Operatoren: Unterstützte Operatoren:

View File

@@ -27,7 +27,7 @@ Berechnung des effektiven Ablaufdatums:
3. Vor jeder Wertprüfung wird geprüft, ob `columnName` in der aktuellen Liste/Bibliothek existiert. Ein fehlendes Feld kann die Regel nicht erfüllen. 3. Vor jeder Wertprüfung wird geprüft, ob `columnName` in der aktuellen Liste/Bibliothek existiert. Ein fehlendes Feld kann die Regel nicht erfüllen.
4. Existiert das Feld und entspricht sein Wert `columnValue`, werden `lifeTime` und `columnRule` dieser Regel verwendet. 4. Existiert das Feld und entspricht sein Wert `columnValue`, werden `lifeTime` und `columnRule` dieser Regel verwendet.
5. Passt keine Regel oder existiert keines der Regelfelder, werden `default.lifeTime` und `default.columnRule` verwendet. 5. Passt keine Regel oder existiert keines der Regelfelder, werden `default.lifeTime` und `default.columnRule` verwendet.
6. Die erste passende `columnRule` bestimmt die Hintergrundfarbe der kompletten Zelle und deren Textfarbe. 6. Die erste passende `columnRule` bestimmt die Hintergrundfarbe der kompletten Listenzeile, deren Textfarbe und die optionale Beschriftung.
Die Berechnung arbeitet mit Kalenderjahren/-monaten/-tagen, nicht mit pauschalen 365-Tage-Jahren. Die Berechnung arbeitet mit Kalenderjahren/-monaten/-tagen, nicht mit pauschalen 365-Tage-Jahren.

View File

@@ -3,7 +3,7 @@
"solution": { "solution": {
"name": "expiry-indicator-client-side-solution", "name": "expiry-indicator-client-side-solution",
"id": "68bb6d2d-9895-45b4-88e8-b98835faa981", "id": "68bb6d2d-9895-45b4-88e8-b98835faa981",
"version": "1.0.5.0", "version": "1.0.7.0",
"includeClientSideAssets": true, "includeClientSideAssets": true,
"skipFeatureDeployment": false, "skipFeatureDeployment": false,
"features": [ "features": [
@@ -11,7 +11,7 @@
"title": "ExpiryIndicator command set registration", "title": "ExpiryIndicator command set registration",
"description": "Registers ExpiryIndicator commands for modern lists and document libraries. Does not provision ExpiryDate.", "description": "Registers ExpiryIndicator commands for modern lists and document libraries. Does not provision ExpiryDate.",
"id": "913402af-ab9a-4974-9f86-5c2159ae41db", "id": "913402af-ab9a-4974-9f86-5c2159ae41db",
"version": "1.0.5.0", "version": "1.0.7.0",
"assets": { "assets": {
"elementManifests": [ "elementManifests": [
"elements.xml" "elements.xml"

View File

@@ -1,6 +1,6 @@
{ {
"name": "expiry-indicator", "name": "expiry-indicator",
"version": "1.0.5", "version": "1.0.7",
"private": true, "private": true,
"engines": { "engines": {
"node": ">=6.9.0 <9.0.0" "node": ">=6.9.0 <9.0.0"

View File

@@ -4,7 +4,7 @@
"alias": "ExpiryIndicatorFieldCustomizer", "alias": "ExpiryIndicatorFieldCustomizer",
"componentType": "Extension", "componentType": "Extension",
"extensionType": "FieldCustomizer", "extensionType": "FieldCustomizer",
"version": "1.0.5", "version": "1.0.7",
"manifestVersion": 2, "manifestVersion": 2,
"requiresCustomScript": false "requiresCustomScript": false
} }

View File

@@ -100,11 +100,17 @@ export default class ExpiryIndicatorFieldCustomizer
this._rememberCellStyle(cell); this._rememberCellStyle(cell);
if (evaluation.matchedRule) { if (evaluation.matchedRule) {
cell.style.backgroundColor = evaluation.matchedRule.backgroundColor; this._getRowStyleTargets(container).forEach((target: HTMLElement): void => {
cell.style.color = evaluation.matchedRule.textColor; this._rememberCellStyle(target);
target.style.backgroundColor = evaluation.matchedRule!.backgroundColor;
target.style.color = evaluation.matchedRule!.textColor;
});
} }
wrapper.textContent = formatDate(evaluation.effectiveExpiryDate); wrapper.textContent = formatDate(evaluation.effectiveExpiryDate);
if (evaluation.matchedRule && evaluation.matchedRule.label) {
wrapper.appendChild(document.createTextNode(' ' + evaluation.matchedRule.label));
}
const calculationHint: string = evaluation.wasCalculated ? ' ' + strings.CalculatedHint : ''; const calculationHint: string = evaluation.wasCalculated ? ' ' + strings.CalculatedHint : '';
cell.title = strings.DaysUntilExpiry.replace('{0}', String(evaluation.daysUntilExpiry)) + calculationHint; cell.title = strings.DaysUntilExpiry.replace('{0}', String(evaluation.daysUntilExpiry)) + calculationHint;
@@ -139,24 +145,59 @@ export default class ExpiryIndicatorFieldCustomizer
} }
private _clear(container: HTMLElement): void { private _clear(container: HTMLElement): void {
this._restoreCellStyle(this._findCellElement(container)); this._getRowStyleTargets(container).forEach((target: HTMLElement): void => {
this._restoreCellStyle(target);
});
while (container.firstChild) { while (container.firstChild) {
container.removeChild(container.firstChild); container.removeChild(container.firstChild);
} }
} }
private _findCellElement(container: HTMLElement): HTMLElement { private _getRowStyleTargets(container: HTMLElement): HTMLElement[] {
const row: HTMLElement | undefined = this._findRowElement(container);
if (!row) {
return [this._findCellElement(container)];
}
const targets: HTMLElement[] = [row];
const cells: NodeListOf<Element> = row.querySelectorAll('[role="gridcell"]');
for (let index: number = 0; index < cells.length; index++) {
targets.push(cells[index] as HTMLElement);
}
return targets;
}
private _findRowElement(container: HTMLElement): HTMLElement | undefined {
let current: HTMLElement | null = container; let current: HTMLElement | null = container;
let level: number = 0; let level: number = 0;
while (current && level < 8) { while (current && level < 16) {
const className: string = typeof current.className === 'string' ? current.className : ''; const className: string = typeof current.className === 'string' ? current.className : '';
if (current.getAttribute('role') === 'gridcell' || className.indexOf('ms-DetailsRow-cell') >= 0) { if (current.getAttribute('role') === 'row' || className.indexOf('ms-DetailsRow') >= 0) {
return current; return current;
} }
current = current.parentElement; current = current.parentElement;
level++; level++;
} }
return container; return undefined;
}
private _findCellElement(container: HTMLElement): HTMLElement {
let current: HTMLElement | null = container;
let gridCell: HTMLElement | undefined;
let level: number = 0;
while (current && level < 12) {
const className: string = typeof current.className === 'string' ? current.className : '';
if (current.getAttribute('data-automationid') === 'DetailsRowCell' ||
className.indexOf('ms-DetailsRow-cell') >= 0) {
return current;
}
if (!gridCell && current.getAttribute('role') === 'gridcell') {
gridCell = current;
}
current = current.parentElement;
level++;
}
return gridCell || container;
} }
private _rememberCellStyle(cell: HTMLElement): void { private _rememberCellStyle(cell: HTMLElement): void {

View File

@@ -4,7 +4,7 @@
"alias": "ExpiryIndicatorCommandSet", "alias": "ExpiryIndicatorCommandSet",
"componentType": "Extension", "componentType": "Extension",
"extensionType": "ListViewCommandSet", "extensionType": "ListViewCommandSet",
"version": "1.0.5", "version": "1.0.7",
"manifestVersion": 2, "manifestVersion": 2,
"requiresCustomScript": false, "requiresCustomScript": false,
"items": { "items": {