/** * Copyright (c) Cisco Systems, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * */ import { LitElement, html, property, PropertyValues, internalProperty } from "lit-element"; import { classMap } from "lit-html/directives/class-map"; import { DateTime } from "luxon"; import styles from "./scss/module.scss"; import { lookupIcon } from "./utils"; import { customElementWithCheck } from "@/mixins"; import * as iconData from "@/assets/defaultIconsV2.json"; import { TimelineV2 } from "./TimelineV2"; import { nothing, TemplateResult } from "lit-html"; import * as linkify from "linkifyjs"; import "@momentum-ui/web-components/dist/comp/md-modal"; const boxOpenImage = "https://cjaas.cisco.com/assets/img/box-open-120.png"; export namespace TimelineItemV2 { export type ShowcaseList = string[]; @customElementWithCheck("cjaas-timeline-item-v2") export class ELEMENT extends LitElement { /** * @attr title */ @property({ type: String, attribute: "title" }) title = ""; /** * @attr description */ @property({ type: String }) description = ""; /** * @attr icon-type */ @property({ type: String, attribute: "icon-type" }) iconType = "meetings_16"; @property({ type: String, attribute: "event-source" }) eventSource = ""; /** * @attr time */ @property({ type: String }) time = ""; /** * @prop data */ @property() data: any = null; /** * @prop isMostRecent */ @property({ type: Boolean, attribute: "is-most-recent" }) isMostRecent = false; @property({ type: Boolean, attribute: "is-ongoing" }) isOngoing = false; @property({ type: Boolean, attribute: "empty-most-recent" }) emptyMostRecent = false; /** * Property to pass in data template to set color and icon settings and showcased data * @prop eventIconTemplate */ @property({ attribute: false }) eventIconTemplate: TimelineV2.TimelineCustomizations = iconData; @internalProperty() formattedTime = ""; @internalProperty() formattedMonth = ""; @internalProperty() formattedDay = ""; @internalProperty() isHovered = false; @internalProperty() areDetailsExpanded = false; @internalProperty() isWxccEvent = false; @internalProperty() hasData = false; updated(changedProperties: PropertyValues) { super.updated(changedProperties); if (changedProperties.has("time")) { this.formattedTime = this.formatTime(this.time); } if (changedProperties.has("eventSource")) { this.isWxccEvent = this.eventSource.includes("wxcc"); } if (changedProperties.has("data")) { this.hasData = this.data && !!Object.values(this.data)?.length; } } handleMouseEnter() { if (!this.areDetailsExpanded) { this.isHovered = true; } } handleMouseLeave() { if (!this.areDetailsExpanded) { this.isHovered = false; } } formatTime(time: string) { const dateTimeObject = DateTime.fromISO(time); this.formattedDay = dateTimeObject?.day.toString() || ""; this.formattedMonth = dateTimeObject?.monthShort; return dateTimeObject.toLocaleString({ hour: "2-digit", minute: "2-digit" }); } static get styles() { return styles; } private get groupClassMap() { return { "most-recent": this.isMostRecent, "empty-most-recent": this.emptyMostRecent, "expanded-details": this.areDetailsExpanded, "is-wxcc-event": this.isWxccEvent, "hovered-over": this.isHovered, "has-data": this.hasData, "are-details-expanded": this.areDetailsExpanded, }; } getIconName(iconType: string) { let iconKeyword; let iconData; if (this.data) { iconKeyword = iconType || this.data?.channelType || ""; iconData = lookupIcon(iconKeyword, this.eventIconTemplate!); } return iconData?.name; } renderEventIcon(iconName: string, size = 16) { return html` `; } renderLeftSection(iconName: string) { if (this.isMostRecent) { return html`
${this.formattedMonth}${this.formattedDay}
`; } else { return html`
${this.renderEventIcon(iconName)}
`; } } renderOngoingStatus() { return html` Ongoing `; } parseSubTextUrlRecursively(stringValue: string): TemplateResult { if (!stringValue.includes("](")) { return html` ${stringValue} `; } const firstBracketIndex = stringValue.indexOf("["); const endBracket = stringValue.indexOf("]"); const endParentheses = stringValue.indexOf(")"); const urlText = stringValue.slice(firstBracketIndex + 1, endBracket); const urlAddress = stringValue.slice(endBracket + 2, endParentheses); const textBefore = stringValue.slice(0, firstBracketIndex); const textAfter = stringValue.slice(endParentheses + 1); const urlLink = urlAddress.startsWith("www") ? `//${urlAddress}` : urlAddress; const renderValue = html` ${textBefore}${urlText} `; return html` ${renderValue} ${this.parseSubTextUrlRecursively(textAfter)} `; } /** * @method copyValue * @param {Event} e * Copies text to clipboard */ copyValue = (e: Event) => { /* Get the text field */ const copyText = (e.target as HTMLElement).innerText as string; /* Copy the text inside the text field */ navigator.clipboard.writeText(copyText); }; /** * @method createTableRecursive * @param data * @returns Template * Builds the timeline item's data table */ createTableRecursive(data: any): any { if (!data) { return nothing; } else { return html` ${Object.keys(data).map((x: string) => { if (x === "uiData") { return; } if (typeof data[x] !== "object") { const dataValue = data[x]; if (dataValue) { let renderValue = dataValue || "-"; if (typeof dataValue === "string") { if (linkify.test(dataValue, "url")) { const urlLink = dataValue.startsWith("www") ? `//${dataValue}` : dataValue; renderValue = html` ${renderValue} `; } else { renderValue = this.parseSubTextUrlRecursively(dataValue); } } return html`
${x}
this.copyValue(e)}> ${renderValue}
`; } } else { return this.createTableRecursive(data[x]); } })} `; } } expandEventDetails() { this.areDetailsExpanded = true; } renderExpandingArrow() { if (this.isHovered && !this.isWxccEvent && this.hasData) { return html` `; } else { return nothing; } } renderDetailsModal() { return html` { this.areDetailsExpanded = false; this.isHovered = false; }} >
Activity Details
${this.createTableRecursive(this.data)}
`; } render() { const iconName = this.getIconName(this.iconType); if (this.emptyMostRecent) { return html`

Most Recent

failure-image
No Data
`; } else { return html`
this.handleMouseEnter()} @mouseleave=${() => this.handleMouseLeave()} >

Most Recent

${this.renderLeftSection(iconName)}
${this.isMostRecent ? this.renderEventIcon(iconName, 14) : nothing} ${this.title} ${this.isOngoing ? this.renderOngoingStatus() : nothing}
${this.formattedTime} ${this.description}
${this.renderExpandingArrow()}
${this.renderDetailsModal()}
`; } } } } declare global { interface HTMLElementTagNameMap { "cjaas-timeline-item-v2": TimelineItemV2.ELEMENT; } }