| /*! |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| /* global window, moment, convertSecsToHumanReadable */ |
| |
| // We don't re-import moment again, otherwise webpack will include it twice in the bundle! |
| import { escapeHtml } from './main'; |
| import { defaultFormat, formatDateTime } from './datetime_utils'; |
| import { dagTZ } from './dag'; |
| import { finalStatesMap } from './utils'; |
| |
| function makeDateTimeHTML(start, end) { |
| // check task ended or not |
| const isEnded = end && end instanceof moment && end.isValid(); |
| return `Started: ${start.format(defaultFormat)}<br>Ended: ${isEnded ? end.format(defaultFormat) : 'Not ended yet'}<br>`; |
| } |
| |
| function generateTooltipDateTimes(startTime, endTime, dagTimezone) { |
| if (!startTime) { |
| return '<br><em>Not yet started</em>'; |
| } |
| |
| const tzFormat = 'z (Z)'; |
| const localTZ = moment.defaultZone.name.toUpperCase(); |
| const startDate = moment.utc(startTime); |
| const endDate = moment.utc(endTime); |
| const dagTz = dagTimezone.toUpperCase(); |
| |
| // Generate UTC Start and End Date |
| let tooltipHTML = '<br><strong>UTC:</strong><br>'; |
| tooltipHTML += makeDateTimeHTML(startDate, endDate); |
| |
| // Generate User's Local Start and End Date, unless it's UTC |
| if (localTZ !== 'UTC') { |
| startDate.tz(localTZ); |
| tooltipHTML += `<br><strong>Local: ${startDate.format(tzFormat)}</strong><br>`; |
| const localEndDate = endDate && endDate instanceof moment ? endDate.tz(localTZ) : endDate; |
| tooltipHTML += makeDateTimeHTML(startDate, localEndDate); |
| } |
| |
| // Generate DAG's Start and End Date |
| if (dagTz !== 'UTC' && dagTz !== localTZ) { |
| startDate.tz(dagTz); |
| tooltipHTML += `<br><strong>DAG's TZ: ${startDate.format(tzFormat)}</strong><br>`; |
| const dagTZEndDate = endDate && endDate instanceof moment ? endDate.tz(dagTz) : endDate; |
| tooltipHTML += makeDateTimeHTML(startDate, dagTZEndDate); |
| } |
| |
| return tooltipHTML; |
| } |
| |
| export default function tiTooltip(ti, { includeTryNumber = false } = {}) { |
| let tt = ''; |
| if (ti.state !== undefined) { |
| tt += `<strong>Status:</strong> ${escapeHtml(ti.state)}<br><br>`; |
| } |
| if (ti.mapped_states) { |
| const numMap = finalStatesMap(); |
| ti.mapped_states.forEach((s) => { |
| const stateKey = s || 'no_status'; |
| if (numMap.has(stateKey)) numMap.set(stateKey, numMap.get(stateKey) + 1); |
| }); |
| tt += `<strong>${escapeHtml(ti.mapped_states.length)} ${ti.mapped_states.length === 1 ? 'Task' : 'Tasks'} Mapped</strong><br />`; |
| numMap.forEach((key, val) => { |
| if (key > 0) { |
| tt += `<span style="margin-left: 15px">${escapeHtml(val)}: ${escapeHtml(key)}</span><br />`; |
| } |
| }); |
| tt += '<br />'; |
| } |
| if (ti.task_id !== undefined) { |
| tt += `Task_id: ${escapeHtml(ti.task_id)}<br>`; |
| } |
| tt += `Run: ${formatDateTime(ti.execution_date)}<br>`; |
| if (ti.run_id !== undefined) { |
| tt += `Run Id: <nobr>${escapeHtml(ti.run_id)}</nobr><br>`; |
| } |
| // Show mapped index for specific child instance, but not for a summary instance |
| if (ti.map_index >= 0 && !ti.mapped_states) { |
| tt += `Map Index: ${escapeHtml(ti.map_index)}<br>`; |
| } |
| if (ti.operator !== undefined) { |
| tt += `Operator: ${escapeHtml(ti.operator)}<br>`; |
| } |
| |
| // Calculate duration on the fly if task instance is still running |
| if (ti.state === 'running') { |
| const startDate = ti.start_date instanceof moment ? ti.start_date : moment(ti.start_date); |
| ti.duration = moment().diff(startDate, 'second'); |
| } else if (!ti.duration && ti.end_date) { |
| const startDate = ti.start_date instanceof moment ? ti.start_date : moment(ti.start_date); |
| const endDate = ti.end_date instanceof moment ? ti.end_date : moment(ti.end_date); |
| ti.duration = moment(endDate).diff(startDate, 'second'); |
| } |
| |
| tt += `Duration: ${escapeHtml(convertSecsToHumanReadable(ti.duration))}<br>`; |
| |
| const intervalStart = ti.data_interval_start; |
| const intervalEnd = ti.data_interval_end; |
| if (intervalStart && intervalEnd) { |
| tt += '<br><strong>Data Interval:</strong><br>'; |
| tt += `Start: ${formatDateTime(intervalStart)}<br>`; |
| tt += `End: ${formatDateTime(intervalEnd)}<br>`; |
| } |
| |
| if (includeTryNumber) { |
| tt += `Try Number: ${escapeHtml(ti.try_number)}<br>`; |
| } |
| // dagTZ has been defined in dag.html |
| tt += generateTooltipDateTimes(ti.start_date, ti.end_date, dagTZ || 'UTC'); |
| return tt; |
| } |
| |
| export function taskNoInstanceTooltip(taskId, task) { |
| let tt = ''; |
| if (taskId) { |
| tt += `Task_id: ${escapeHtml(taskId)}<br>`; |
| } |
| if (task.task_type !== undefined) { |
| tt += `Operator: ${escapeHtml(task.task_type)}<br>`; |
| } |
| tt += '<br><em>DAG has yet to run.</em>'; |
| return tt; |
| } |
| |
| window.tiTooltip = tiTooltip; |
| window.taskNoInstanceTooltip = taskNoInstanceTooltip; |