|
|
@ -9,12 +9,12 @@ import { |
|
|
|
} from '../types'; |
|
|
|
} from '../types'; |
|
|
|
|
|
|
|
|
|
|
|
import { convertTimestampToDate, convertTimeZoneTypeToName, getCurrentDashboardUid } from '../../../utils'; |
|
|
|
import { convertTimestampToDate, convertTimeZoneTypeToName, getCurrentDashboardUid } from '../../../utils'; |
|
|
|
import { CLOSE_ICON_BASE_64, DOWNLOAD_ICON_BASE_64, SELECT_ICON_BASE_64, UNSELECT_ICON_BASE_64 } from '../../../icons'; |
|
|
|
import { CLOSE_ICON_BASE_64, OPTIONS_ICON_BASE_64, SELECT_ICON_BASE_64, UNSELECT_ICON_BASE_64 } from '../../../icons'; |
|
|
|
|
|
|
|
|
|
|
|
import { deleteTask, getStaticFile, getTasks, queryApi } from '../../../services/api_service'; |
|
|
|
import { deleteTask, getStaticFile, getTasks, queryApi } from '../../../services/api_service'; |
|
|
|
import { getDashboardByUid, getDatasources } from '../../../services/grafana_backend_service'; |
|
|
|
import { getDashboardByUid, getDatasources } from '../../../services/grafana_backend_service'; |
|
|
|
|
|
|
|
|
|
|
|
import { contextSrv } from 'grafana/app/core/core'; |
|
|
|
import { appEvents, contextSrv } from 'grafana/app/core/core'; |
|
|
|
import { css } from '@emotion/css'; |
|
|
|
import { css } from '@emotion/css'; |
|
|
|
|
|
|
|
|
|
|
|
import { |
|
|
|
import { |
|
|
@ -40,6 +40,7 @@ import { |
|
|
|
DataSourceSettings, |
|
|
|
DataSourceSettings, |
|
|
|
TimeRange, |
|
|
|
TimeRange, |
|
|
|
OrgRole, |
|
|
|
OrgRole, |
|
|
|
|
|
|
|
AppEvents, |
|
|
|
} from '@grafana/data'; |
|
|
|
} from '@grafana/data'; |
|
|
|
import { RefreshEvent } from '@grafana/runtime'; |
|
|
|
import { RefreshEvent } from '@grafana/runtime'; |
|
|
|
|
|
|
|
|
|
|
@ -297,7 +298,7 @@ export function Panel({ width, height, timeRange, eventBus, timeZone }: Props) { |
|
|
|
name: 'A', |
|
|
|
name: 'A', |
|
|
|
fields: [ |
|
|
|
fields: [ |
|
|
|
{ |
|
|
|
{ |
|
|
|
name: 'Time', |
|
|
|
name: 'Status Updated At', |
|
|
|
type: FieldType.number, |
|
|
|
type: FieldType.number, |
|
|
|
values: _.map(sortedTasks, (task) => convertTimestampToDate(task.progress?.time)), |
|
|
|
values: _.map(sortedTasks, (task) => convertTimestampToDate(task.progress?.time)), |
|
|
|
}, |
|
|
|
}, |
|
|
@ -342,41 +343,25 @@ export function Panel({ width, height, timeRange, eventBus, timeZone }: Props) { |
|
|
|
values: _.map(sortedTasks, (task) => task.progress?.errorMessage || '-'), |
|
|
|
values: _.map(sortedTasks, (task) => task.progress?.errorMessage || '-'), |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
{ |
|
|
|
name: 'Download CSV', |
|
|
|
name: 'Actions', |
|
|
|
type: FieldType.string, |
|
|
|
type: FieldType.string, |
|
|
|
values: _.map(sortedTasks, () => `data:image/png;base64,${DOWNLOAD_ICON_BASE_64}`), |
|
|
|
values: _.map(sortedTasks, (task) => { |
|
|
|
|
|
|
|
switch (task.progress?.status) { |
|
|
|
|
|
|
|
case ExportStatus.FINISHED: |
|
|
|
|
|
|
|
return `data:image/png;base64,${OPTIONS_ICON_BASE_64}`; |
|
|
|
|
|
|
|
case ExportStatus.ERROR: |
|
|
|
|
|
|
|
return `data:image/png;base64,${CLOSE_ICON_BASE_64}`; |
|
|
|
|
|
|
|
case ExportStatus.EXPORTING: |
|
|
|
|
|
|
|
return ``; |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
throw new Error(`Unknown exporting status: ${task.progress?.status}`); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}), |
|
|
|
config: { |
|
|
|
config: { |
|
|
|
custom: { |
|
|
|
custom: { |
|
|
|
filterable: false, |
|
|
|
filterable: false, |
|
|
|
displayMode: 'image', |
|
|
|
displayMode: 'image', |
|
|
|
}, |
|
|
|
}, |
|
|
|
links: [ |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
targetBlank: false, |
|
|
|
|
|
|
|
title: 'Download', |
|
|
|
|
|
|
|
url: '#', |
|
|
|
|
|
|
|
onClick: (event: DataLinkClickEvent) => onDownloadClick(event), |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
], |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
name: 'Delete task', |
|
|
|
|
|
|
|
type: FieldType.string, |
|
|
|
|
|
|
|
values: _.map(tasks, () => `data:image/png;base64,${CLOSE_ICON_BASE_64}`), |
|
|
|
|
|
|
|
config: { |
|
|
|
|
|
|
|
custom: { |
|
|
|
|
|
|
|
filterable: false, |
|
|
|
|
|
|
|
displayMode: 'image', |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
links: [ |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
targetBlank: false, |
|
|
|
|
|
|
|
title: 'Delete', |
|
|
|
|
|
|
|
url: '#', |
|
|
|
|
|
|
|
onClick: (event: DataLinkClickEvent) => onDeleteClick(event), |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
], |
|
|
|
|
|
|
|
}, |
|
|
|
}, |
|
|
|
}, |
|
|
|
}, |
|
|
|
], |
|
|
|
], |
|
|
@ -391,22 +376,57 @@ export function Panel({ width, height, timeRange, eventBus, timeZone }: Props) { |
|
|
|
theme: createTheme(), |
|
|
|
theme: createTheme(), |
|
|
|
replaceVariables: (value: string) => value, |
|
|
|
replaceVariables: (value: string) => value, |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// @ts-expect-error
|
|
|
|
|
|
|
|
dataFrames[0].fields[9].getLinks = (cell: { valueRowIndex: number }) => { |
|
|
|
|
|
|
|
const rowIndex = cell.valueRowIndex; |
|
|
|
|
|
|
|
const task = _.find(sortedTasks, (task, idx) => idx === rowIndex); |
|
|
|
|
|
|
|
if (!task) { |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
switch (task.progress?.status) { |
|
|
|
|
|
|
|
case ExportStatus.FINISHED: |
|
|
|
|
|
|
|
return [ |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
targetBlank: false, |
|
|
|
|
|
|
|
title: 'Download', |
|
|
|
|
|
|
|
url: '#', |
|
|
|
|
|
|
|
onClick: () => onDownloadClick(task), |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
targetBlank: false, |
|
|
|
|
|
|
|
title: 'Delete', |
|
|
|
|
|
|
|
url: '#', |
|
|
|
|
|
|
|
onClick: () => onDeleteClick(task), |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
]; |
|
|
|
|
|
|
|
case ExportStatus.ERROR: |
|
|
|
|
|
|
|
return [ |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
targetBlank: false, |
|
|
|
|
|
|
|
title: 'Delete', |
|
|
|
|
|
|
|
url: '#', |
|
|
|
|
|
|
|
onClick: () => onDeleteClick(task), |
|
|
|
|
|
|
|
}, |
|
|
|
|
|
|
|
]; |
|
|
|
|
|
|
|
case ExportStatus.EXPORTING: |
|
|
|
|
|
|
|
return []; |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
throw new Error(`Unknown exporting status: ${task.progress?.status}`); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}; |
|
|
|
return dataFrames[0]; |
|
|
|
return dataFrames[0]; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
async function onDeleteClick(e: DataLinkClickEvent): Promise<void> { |
|
|
|
async function onDeleteClick(taskToDelete: ExportTask): Promise<void> { |
|
|
|
const rowIndex = e.origin.rowIndex; |
|
|
|
await deleteTask(taskToDelete?.id); |
|
|
|
|
|
|
|
|
|
|
|
const task = _.find(tasks, (task, idx) => idx === rowIndex); |
|
|
|
|
|
|
|
await deleteTask(task?.id); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const filteredTasks = _.filter(tasks, (task, idx) => idx !== rowIndex); |
|
|
|
const filteredTasks = _.filter(tasks, (task) => task.id !== taskToDelete.id); |
|
|
|
setTasks(filteredTasks); |
|
|
|
setTasks(filteredTasks); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function onDownloadClick(e: DataLinkClickEvent): void { |
|
|
|
function onDownloadClick(task: ExportTask): void { |
|
|
|
const rowIndex = e.origin.rowIndex; |
|
|
|
appEvents.emit(AppEvents.alertSuccess, ['CSV has started downloading...']); |
|
|
|
const task = _.find(tasks, (task, idx) => idx === rowIndex); |
|
|
|
|
|
|
|
getStaticFile(task?.id); |
|
|
|
getStaticFile(task?.id); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|