import { override } from '@microsoft/decorators'; import { BaseFieldCustomizer, IFieldCustomizerCellEventParameters } from '@microsoft/sp-listview-extensibility'; import { evaluateExpiry, formatDate, parseSharePointDate } from '../../common/ExpiryDateCalculator'; import { ExpiryConfigService } from '../../common/ExpiryConfigService'; import { ExpiryItemService } from '../../common/ExpiryItemService'; import { createDefaultConfig, IExpiryConfig, IExpiryEvaluation, IItemDateValues, resolveBehavior } from '../../common/ExpiryModels'; import styles from './ExpiryIndicatorFieldCustomizer.module.scss'; import * as strings from 'ExpiryIndicatorStrings'; export interface IExpiryIndicatorFieldCustomizerProperties { } export default class ExpiryIndicatorFieldCustomizer extends BaseFieldCustomizer { private _config: IExpiryConfig = createDefaultConfig(); private _itemService: ExpiryItemService; private _itemCache: { [id: string]: Promise } = {}; @override public onInit(): Promise { if (!this.context.pageContext.list) { return Promise.resolve(); } const service: ExpiryConfigService = new ExpiryConfigService( this.context.spHttpClient, this.context.pageContext.web.absoluteUrl ); this._itemService = new ExpiryItemService( this.context.spHttpClient, this.context.pageContext.web.absoluteUrl, this.context.pageContext.list.id.toString() ); return service.getConfig(this.context.pageContext.list.id.toString()) .then((config: IExpiryConfig): void => { this._config = config; }) .catch((): void => { this._config = createDefaultConfig(); }); } @override public onRenderCell(event: IFieldCustomizerCellEventParameters): void { this._clear(event.domElement); const expiry: Date | undefined = parseSharePointDate(event.fieldValue); const createdValue: any = event.listItem && event.listItem.getValueByName ? event.listItem.getValueByName(this._config.baseField) : undefined; const created: Date | undefined = parseSharePointDate(createdValue); const idValue: any = event.listItem && event.listItem.getValueByName ? (event.listItem.getValueByName('ID') || event.listItem.getValueByName('Id')) : undefined; const itemId: number = Number(idValue); if (itemId > 0 && this._itemService) { const requestKey: string = String(itemId); event.domElement.setAttribute('data-expiry-item-id', requestKey); this._renderNeutral(event.domElement, strings.Loading); if (!this._itemCache[requestKey]) { this._itemCache[requestKey] = this._itemService.getItemDates(itemId, this._config); } this._itemCache[requestKey].then((item: IItemDateValues): void => { if (event.domElement.getAttribute('data-expiry-item-id') !== requestKey) { return; } this._clear(event.domElement); this._renderValues(event.domElement, item.created, item.expiry, item.fieldValues); }).catch((): void => { if (event.domElement.getAttribute('data-expiry-item-id') === requestKey) { this._clear(event.domElement); this._renderValues(event.domElement, created, expiry, {}); } }); return; } this._renderValues(event.domElement, created, expiry, {}); } @override public onDisposeCell(event: IFieldCustomizerCellEventParameters): void { this._clear(event.domElement); super.onDisposeCell(event); } private _renderEvaluation(container: HTMLElement, evaluation: IExpiryEvaluation): void { const wrapper: HTMLSpanElement = document.createElement('span'); wrapper.className = styles.cell + (evaluation.wasCalculated ? ' ' + styles.calculated : ''); if (evaluation.matchedRule) { wrapper.style.backgroundColor = evaluation.matchedRule.backgroundColor; wrapper.style.color = evaluation.matchedRule.textColor; } const date: HTMLSpanElement = document.createElement('span'); date.className = styles.date; date.textContent = formatDate(evaluation.effectiveExpiryDate); wrapper.appendChild(date); if (evaluation.matchedRule && evaluation.matchedRule.label) { const label: HTMLSpanElement = document.createElement('span'); label.className = styles.label; label.textContent = evaluation.matchedRule.label; wrapper.appendChild(label); } const calculationHint: string = evaluation.wasCalculated ? ' – ' + strings.CalculatedHint : ''; wrapper.title = strings.DaysUntilExpiry.replace('{0}', String(evaluation.daysUntilExpiry)) + calculationHint; container.appendChild(wrapper); } private _renderValues( container: HTMLElement, created: Date | undefined, expiry: Date | undefined, fieldValues: { [fieldName: string]: any } ): void { if (!expiry && !created) { this._renderNeutral(container, this._config.nullText); return; } const evaluation: IExpiryEvaluation = evaluateExpiry( created || expiry as Date, expiry, this._config, undefined, resolveBehavior(this._config, fieldValues) ); this._renderEvaluation(container, evaluation); } private _renderNeutral(container: HTMLElement, text: string): void { const wrapper: HTMLSpanElement = document.createElement('span'); wrapper.className = styles.cell + ' ' + styles.neutral; wrapper.textContent = text; container.appendChild(wrapper); } private _clear(container: HTMLElement): void { while (container.firstChild) { container.removeChild(container.firstChild); } } }