@@ -4,7 +4,7 @@ import { AppEvents } from '@grafana/data';
44import { getAppEvents } from '@grafana/runtime' ;
55import { getFrontendHostnameDefaults } from './getFrontendHostnameDefaults' ;
66import { generateLinkFromQuery } from './generateLinkFromQuery' ;
7- import type { SharelinkItems , SharelinkTimeRange } from '../../types' ;
7+ import { QueryTypes , type QueryType , type SharelinkItems , type SharelinkTimeRange } from '../../types' ;
88import { SquareShareIcon } from '../common/CustomIcons' ;
99
1010interface SharelinkMenuItemProps {
@@ -13,43 +13,57 @@ interface SharelinkMenuItemProps {
1313 apiBaseUrl ?: string ;
1414 frontendUrl ?: string ;
1515 timeRange ?: SharelinkTimeRange ;
16+ queryType ?: QueryType ;
1617}
1718
1819function openLink ( link : string ) {
1920 window . open ( link , '_blank' , 'noopener,noreferrer' ) ;
2021}
2122
22- async function copyToClipboard ( value : string ) {
23- try {
24- if ( ! navigator . clipboard || typeof navigator . clipboard . writeText !== 'function' ) {
25- throw new Error ( 'Clipboard API not available' ) ;
26- }
23+ function publishAlert ( type : string , message : string ) {
24+ const appEvents = getAppEvents ( ) ;
25+ if ( appEvents ) {
26+ appEvents . publish ( {
27+ type,
28+ payload : [ message ] ,
29+ } ) ;
30+ }
31+ }
2732
28- await navigator . clipboard . writeText ( value ) ;
29- const appEvents = getAppEvents ( ) ;
30- if ( appEvents ) {
31- appEvents . publish ( {
32- type : AppEvents . alertSuccess . name ,
33- payload : [ 'Copied Sift share link to clipboard' ] ,
34- } ) ;
35- }
36- } catch ( err ) {
37- console . error ( 'Failed to copy link' , err ) ;
33+ async function copyToClipboard ( value : string ) {
34+ if ( ! navigator . clipboard || typeof navigator . clipboard . writeText !== 'function' ) {
35+ throw new Error ( 'Clipboard API not available' ) ;
3836 }
37+
38+ await navigator . clipboard . writeText ( value ) ;
3939}
4040
41- export const OpenInSiftButton = ( { className, items, apiBaseUrl, frontendUrl, timeRange } : SharelinkMenuItemProps ) => {
41+ export const OpenInSiftButton = ( {
42+ className,
43+ items,
44+ apiBaseUrl,
45+ frontendUrl,
46+ timeRange,
47+ queryType,
48+ } : SharelinkMenuItemProps ) => {
4249 const { shareLink, disabledReason } = useMemo ( ( ) => {
4350 const trimmedFrontendUrl = frontendUrl ?. trim ( ) ;
4451
52+ if ( queryType === QueryTypes . CALCULATED_CHANNEL ) {
53+ return {
54+ shareLink : null ,
55+ disabledReason : 'Open in Sift is unavailable when Query Mode is set to Calculated Channels' ,
56+ } ;
57+ }
58+
4559 if ( ! apiBaseUrl && ! trimmedFrontendUrl ) {
4660 return {
4761 shareLink : null ,
4862 disabledReason : 'Configure the Sift API REST URL to enable share links' ,
4963 } ;
5064 }
5165
52- if ( ! items || ! items . channelIds || items . channelIds . length === 0 ) {
66+ if ( ! items || items . channelIds . length === 0 ) {
5367 return {
5468 shareLink : null ,
5569 disabledReason : 'Select a channel to enable share links' ,
@@ -63,7 +77,7 @@ export const OpenInSiftButton = ({ className, items, apiBaseUrl, frontendUrl, ti
6377 disabledReason : 'Configure the Sift API REST URL to enable share links' ,
6478 } ;
6579 }
66-
80+
6781 try {
6882 return {
6983 shareLink : generateLinkFromQuery ( hostname , items , timeRange ) ,
@@ -76,7 +90,29 @@ export const OpenInSiftButton = ({ className, items, apiBaseUrl, frontendUrl, ti
7690 disabledReason : 'Failed to generate share link' ,
7791 } ;
7892 }
79- } , [ apiBaseUrl , frontendUrl , items , timeRange ] ) ;
93+ } , [ apiBaseUrl , frontendUrl , items , queryType , timeRange ] ) ;
94+
95+ const handleOpen = ( ) => {
96+ if ( ! shareLink ) {
97+ return ;
98+ }
99+
100+ openLink ( shareLink ) ;
101+ } ;
102+
103+ const handleCopy = async ( ) => {
104+ if ( ! shareLink ) {
105+ return ;
106+ }
107+
108+ try {
109+ await copyToClipboard ( shareLink ) ;
110+
111+ publishAlert ( AppEvents . alertSuccess . name , 'Copied Sift share link to clipboard' ) ;
112+ } catch ( err ) {
113+ console . error ( 'Failed to copy link' , err ) ;
114+ }
115+ } ;
80116
81117 return (
82118 < InlineLabel width = "auto" transparent className = { className } style = { { marginLeft : 'auto' } } >
@@ -87,18 +123,14 @@ export const OpenInSiftButton = ({ className, items, apiBaseUrl, frontendUrl, ti
87123 label = "Open Link"
88124 disabled = { ! shareLink }
89125 onClick = { ( ) => {
90- if ( shareLink ) {
91- openLink ( shareLink ) ;
92- }
126+ handleOpen ( ) ;
93127 } }
94128 />
95129 < Menu . Item
96130 label = { shareLink ? 'Copy to Clipboard' : 'Copy (URL not set)' }
97131 disabled = { ! shareLink }
98132 onClick = { ( ) => {
99- if ( shareLink ) {
100- void copyToClipboard ( shareLink ) ;
101- }
133+ void handleCopy ( ) ;
102134 } }
103135 />
104136 </ Menu . Group >
@@ -108,7 +140,7 @@ export const OpenInSiftButton = ({ className, items, apiBaseUrl, frontendUrl, ti
108140 < Button
109141 onClick = { ( event ) => {
110142 if ( shareLink ) {
111- openLink ( shareLink ) ;
143+ handleOpen ( ) ;
112144 return ;
113145 }
114146 openMenu ( event ) ;
0 commit comments