import { html, css, LitElement, PropertyValues } from 'lit' import { customElement, property, query, state } from 'lit/decorators.js' import { InputData } from './definition-schema' import 'lit-flatpickr' import { LitFlatpickr } from 'lit-flatpickr' import '@material/web/textfield/outlined-text-field.js' import '@material/web/iconbutton/icon-button.js' import '@material/web/icon/icon.js' type Theme = { theme_name: string theme_object: any } export @customElement('widget-filter-calendar-versionplaceholder') class WidgetfilterCalendar extends LitElement { @property({ type: Object }) inputData?: InputData @property({ type: Object }) theme?: Theme @property({ type: String }) route?: string @state() private themeBgColor?: string @state() private themeTitleColor?: string @state() private themeBorderColor?: string @state() private defaultRange: string[] = [] @query('lit-flatpickr') flatpickr?: LitFlatpickr version: string = 'versionplaceholder' update(changedProperties: Map) { if (changedProperties.has('theme')) { this.registerTheme(this.theme) } // Update defaultRange when route or inputData changes if (changedProperties.has('route') || changedProperties.has('inputData')) { this.updateRangeFromRoute() } super.update(changedProperties) } protected firstUpdated(_changedProperties: PropertyValues): void { this.registerTheme(this.theme) this.updateRangeFromRoute() } formatDateForFlatpickr(date: Date): string { const year = date.getFullYear() const month = String(date.getMonth() + 1).padStart(2, '0') const day = String(date.getDate()).padStart(2, '0') const hours = String(date.getHours()).padStart(2, '0') const minutes = String(date.getMinutes()).padStart(2, '0') const seconds = String(date.getSeconds()).padStart(2, '0') return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}` } updateRangeFromRoute() { if (!this.route || !this.inputData || !this.flatpickr) return const queryString = this.route.split('?')[1] || '' const searchParams = new URLSearchParams(queryString) const isRangeMode = !!(this.inputData.startKey && this.inputData.endKey) if (isRangeMode) { // Range mode: try to get both start and end const startTimestamp = this.inputData.startKey ? searchParams.get(this.inputData.startKey) : null const endTimestamp = this.inputData.endKey ? searchParams.get(this.inputData.endKey) : null if (startTimestamp && endTimestamp) { const startDate = new Date(parseInt(startTimestamp)) const endDate = new Date(parseInt(endTimestamp)) this.defaultRange = [ this.formatDateForFlatpickr(startDate), this.formatDateForFlatpickr(endDate) ] this.flatpickr?.setDate([startDate, endDate], false, 'Y-m-d H:i:S') } else if (startTimestamp) { const startDate = new Date(parseInt(startTimestamp)) this.defaultRange = [this.formatDateForFlatpickr(startDate)] this.flatpickr?.setDate([startDate], false, 'Y-m-d H:i:S') } else { this.defaultRange = [] this.flatpickr?.clear() } } else { // Single date mode: use whichever key is provided const singleKey = this.inputData.startKey || this.inputData.endKey const timestamp = singleKey ? searchParams.get(singleKey) : null if (timestamp) { const date = new Date(parseInt(timestamp)) this.defaultRange = [this.formatDateForFlatpickr(date)] if (this.flatpickr) { this.flatpickr.setDate([date], false, 'Y-m-d H:i:S') } } else { this.defaultRange = [] if (this.flatpickr) { this.flatpickr.clear() } } } } registerTheme(theme?: Theme) { const cssTextColor = getComputedStyle(this).getPropertyValue('--re-text-color').trim() const cssBgColor = getComputedStyle(this).getPropertyValue('--re-tile-background-color').trim() const cssBorderColor = getComputedStyle(this).getPropertyValue('--re-tile-border-color').trim() this.themeBgColor = cssBgColor || this.theme?.theme_object?.backgroundColor || 'transparent' this.themeTitleColor = cssTextColor || this.theme?.theme_object?.title?.textStyle?.color || 'black' this.themeBorderColor = cssBorderColor || this.theme?.theme_object?.title?.textStyle?.color || 'black' } handleSelectionChange(event: Event) { const timeRange = this.flatpickr?.getSelectedDates() const start = timeRange?.[0] const end = timeRange?.[1] // Update defaultRange to reflect current selection (for X button visibility) if (start && end) { this.defaultRange = [this.formatDateForFlatpickr(start), this.formatDateForFlatpickr(end)] } else if (start) { this.defaultRange = [this.formatDateForFlatpickr(start)] } else { this.defaultRange = [] } // Get current URL and its search parameters // Extract only the query string part (after ?) const queryString = this.route?.split('?')[1] || '' const searchParams = new URLSearchParams(queryString) // For range mode: use both start and end // For single mode: use only startKey (or endKey if startKey is not provided) const isRangeMode = !!(this.inputData?.startKey && this.inputData?.endKey) const params: Record = {} if (isRangeMode) { // Range mode: set both start and end if (this.inputData?.startKey) { if (start) { searchParams.set(this.inputData.startKey, String(start.getTime())) params[this.inputData.startKey] = String(start.getTime()) } else { searchParams.delete(this.inputData.startKey) params[this.inputData.startKey] = undefined } } if (this.inputData?.endKey) { if (end) { searchParams.set(this.inputData.endKey, String(end.getTime())) params[this.inputData.endKey] = String(end.getTime()) } else { searchParams.delete(this.inputData.endKey) params[this.inputData.endKey] = undefined } } } else { // Single date mode: use whichever key is provided const singleKey = this.inputData?.startKey || this.inputData?.endKey if (singleKey) { if (start) { searchParams.set(singleKey, String(start.getTime())) params[singleKey] = String(start.getTime()) } else { searchParams.delete(singleKey) params[singleKey] = undefined } } } // Construct the new URL with updated parameters const navEvent = new CustomEvent('param-submit', { detail: { params }, bubbles: true, composed: true }) this.dispatchEvent(navEvent) } handleClear(e: Event) { e.stopPropagation() this.defaultRange = [] if (this.flatpickr) { this.flatpickr.clear() } this.handleSelectionChange(e) } static styles = css` :host { display: block; container-type: size; width: 100%; } .wrapper { display: flex; flex-direction: column; justify-content: center; align-items: stretch; font-family: sans-serif; padding: 2cqh 2cqw; height: 100%; box-sizing: border-box; } input { padding: 8px; width: 100%; font-size: 16px; outline: none; border-radius: 6px; box-sizing: border-box; border: 1px solid #ddd; outline: none; } md-outlined-text-field { --md-outlined-text-field-container-shape: 4px; --md-outlined-field-top-space: 8px; --md-outlined-field-bottom-space: 8px; --md-outlined-field-leading-space: 12px; --md-outlined-field-trailing-space: 12px; min-height: 40px; height: 40px; } lit-flatpickr { width: 100%; background-color: transparent; overflow: visible; } ` render() { const fontColor = this.themeTitleColor const bgColor = this.themeBgColor const isRangeMode = !!(this.inputData?.startKey && this.inputData?.endKey) return html`
${this.defaultRange.length > 0 ? html` close ` : ''}
` } }