diff --git a/.github/workflows/on_push_go.yml b/.github/workflows/on_push_go.yml index aeb78f10d59..9c4b5f093e7 100644 --- a/.github/workflows/on_push_go.yml +++ b/.github/workflows/on_push_go.yml @@ -13,6 +13,7 @@ concurrency: jobs: test: + name: Test runs-on: ubuntu-latest steps: diff --git a/.github/workflows/on_push_ui.yml b/.github/workflows/on_push_ui.yml index 210fd0d0f28..1e5c0c52e8f 100644 --- a/.github/workflows/on_push_ui.yml +++ b/.github/workflows/on_push_ui.yml @@ -13,6 +13,7 @@ concurrency: jobs: test: + name: Test runs-on: ubuntu-latest steps: diff --git a/.github/workflows/on_release.yml b/.github/workflows/on_release.yml index 2dcc7e4897f..64bae9f6d99 100644 --- a/.github/workflows/on_release.yml +++ b/.github/workflows/on_release.yml @@ -9,7 +9,8 @@ permissions: contents: write jobs: - goreleaser: + release: + name: Release runs-on: ubuntu-latest-m steps: - name: Checkout diff --git a/Makefile b/Makefile index 1e9bfbf8134..1d3d1ce2001 100644 --- a/Makefile +++ b/Makefile @@ -225,6 +225,13 @@ golangci-lint: $(GOLANGCI_LINT) --config .golangci.toml \ $(GO_FILES) +lint-fix: $(GOLANGCI_LINT) + @echo "lint via golangci-lint" + $(GOLANGCI_LINT) run \ + --config .golangci.toml \ + --fix \ + $(GO_FILES) + lint-go: golangci-lint ## Run all code checks for backend. You can use GO_FILES to specify exact files to check # with disabled SC1071 we are ignored some TCL,Expect `/usr/bin/env expect` scripts diff --git a/conf/defaults.ini b/conf/defaults.ini index 29cb40206c5..f0d51d8b23f 100644 --- a/conf/defaults.ini +++ b/conf/defaults.ini @@ -1357,6 +1357,10 @@ news_feed_enabled = true # Set the number of data source queries that can be executed concurrently in mixed queries. Default is the number of CPUs. concurrent_query_limit = +[kiosk] +# Enable the kiosk section +mode = off + #################################### Query History ############################# [query_history] # Enable the Query history diff --git a/packages/grafana-data/src/types/config.ts b/packages/grafana-data/src/types/config.ts index 5703028f2cb..83fb225b79a 100644 --- a/packages/grafana-data/src/types/config.ts +++ b/packages/grafana-data/src/types/config.ts @@ -170,6 +170,7 @@ export interface GrafanaConfig { alertingMinInterval: number; authProxyEnabled: boolean; exploreEnabled: boolean; + kioskMode: string; queryHistoryEnabled: boolean; helpEnabled: boolean; profileEnabled: boolean; diff --git a/packages/grafana-runtime/src/config.ts b/packages/grafana-runtime/src/config.ts index 2709d5cf9a6..ff1a190fd6c 100644 --- a/packages/grafana-runtime/src/config.ts +++ b/packages/grafana-runtime/src/config.ts @@ -63,6 +63,7 @@ export class GrafanaBootConfig implements GrafanaConfig { angularSupportEnabled = false; authProxyEnabled = false; exploreEnabled = false; + kioskMode = 'off'; queryHistoryEnabled = false; helpEnabled = false; profileEnabled = false; diff --git a/pkg/api/dtos/frontend_settings.go b/pkg/api/dtos/frontend_settings.go index 166dae62160..be08b576e87 100644 --- a/pkg/api/dtos/frontend_settings.go +++ b/pkg/api/dtos/frontend_settings.go @@ -146,15 +146,16 @@ type FrontendSettingsDTO struct { LiveEnabled bool `json:"liveEnabled"` AutoAssignOrg bool `json:"autoAssignOrg"` - VerifyEmailEnabled bool `json:"verifyEmailEnabled"` - SigV4AuthEnabled bool `json:"sigV4AuthEnabled"` - AzureAuthEnabled bool `json:"azureAuthEnabled"` - RbacEnabled bool `json:"rbacEnabled"` - ExploreEnabled bool `json:"exploreEnabled"` - HelpEnabled bool `json:"helpEnabled"` - ProfileEnabled bool `json:"profileEnabled"` - NewsFeedEnabled bool `json:"newsFeedEnabled"` - QueryHistoryEnabled bool `json:"queryHistoryEnabled"` + VerifyEmailEnabled bool `json:"verifyEmailEnabled"` + SigV4AuthEnabled bool `json:"sigV4AuthEnabled"` + AzureAuthEnabled bool `json:"azureAuthEnabled"` + RbacEnabled bool `json:"rbacEnabled"` + ExploreEnabled bool `json:"exploreEnabled"` + KioskMode string `json:"kioskMode"` + HelpEnabled bool `json:"helpEnabled"` + ProfileEnabled bool `json:"profileEnabled"` + NewsFeedEnabled bool `json:"newsFeedEnabled"` + QueryHistoryEnabled bool `json:"queryHistoryEnabled"` GoogleAnalyticsId string `json:"googleAnalyticsId"` GoogleAnalytics4Id string `json:"googleAnalytics4Id"` diff --git a/pkg/api/frontendsettings.go b/pkg/api/frontendsettings.go index 215714b6f83..1edb9da0f8b 100644 --- a/pkg/api/frontendsettings.go +++ b/pkg/api/frontendsettings.go @@ -129,6 +129,7 @@ func (hs *HTTPServer) getFrontendSettings(c *contextmodel.ReqContext) (*dtos.Fro ProfileEnabled: setting.ProfileEnabled, NewsFeedEnabled: setting.NewsFeedEnabled, QueryHistoryEnabled: hs.Cfg.QueryHistoryEnabled, + KioskMode: setting.KioskMode, GoogleAnalyticsId: hs.Cfg.GoogleAnalyticsID, GoogleAnalytics4Id: hs.Cfg.GoogleAnalytics4ID, GoogleAnalytics4SendManualPageViews: hs.Cfg.GoogleAnalytics4SendManualPageViews, diff --git a/pkg/services/navtree/navtreeimpl/navtree.go b/pkg/services/navtree/navtreeimpl/navtree.go index e6c7b6c36b6..80af7dbd819 100644 --- a/pkg/services/navtree/navtreeimpl/navtree.go +++ b/pkg/services/navtree/navtreeimpl/navtree.go @@ -4,20 +4,21 @@ import ( "fmt" "sort" + "github.com/grafana/grafana/pkg/models/roletype" + "github.com/grafana/grafana/pkg/services/datasources" + "github.com/grafana/grafana/pkg/services/org" + "github.com/grafana/grafana/pkg/api/dtos" "github.com/grafana/grafana/pkg/infra/kvstore" "github.com/grafana/grafana/pkg/infra/log" - "github.com/grafana/grafana/pkg/models/roletype" ac "github.com/grafana/grafana/pkg/services/accesscontrol" "github.com/grafana/grafana/pkg/services/apikey" "github.com/grafana/grafana/pkg/services/auth/identity" contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model" "github.com/grafana/grafana/pkg/services/dashboards" - "github.com/grafana/grafana/pkg/services/datasources" "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/services/licensing" "github.com/grafana/grafana/pkg/services/navtree" - "github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings" "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore" pref "github.com/grafana/grafana/pkg/services/preference" @@ -476,7 +477,6 @@ func (s *ServiceImpl) buildAlertNavLinks(c *contextmodel.ReqContext) *navtree.Na return &alertNav } - return nil } diff --git a/pkg/setting/setting.go b/pkg/setting/setting.go index 45d9e2ae608..c22e6ca424a 100644 --- a/pkg/setting/setting.go +++ b/pkg/setting/setting.go @@ -130,6 +130,9 @@ var ( // Explore UI ExploreEnabled bool + //kiosk mode + KioskMode string + // Help UI HelpEnabled bool @@ -1156,6 +1159,9 @@ func (cfg *Cfg) Load(args CommandLineArgs) error { explore := iniFile.Section("explore") ExploreEnabled = explore.Key("enabled").MustBool(true) + kiosk := iniFile.Section("kiosk") + KioskMode = valueAsString(kiosk, "mode", "off") + help := iniFile.Section("help") HelpEnabled = help.Key("enabled").MustBool(true) diff --git a/public/app/core/components/AppChrome/AppChrome.test.tsx b/public/app/core/components/AppChrome/AppChrome.test.tsx index a4c4a40e43b..20926a5d4e1 100644 --- a/public/app/core/components/AppChrome/AppChrome.test.tsx +++ b/public/app/core/components/AppChrome/AppChrome.test.tsx @@ -41,7 +41,7 @@ const mockSearchResult: QueryResponse = { view: new DataFrameView(searchData), }; -const setup = (children: ReactNode) => { +const setup = (children: ReactNode, hideSearch?: boolean) => { config.bootData.navTree = [ { id: HOME_NAV_ID, @@ -67,7 +67,7 @@ const setup = (children: ReactNode) => { const renderResult = render( - +
{children}
@@ -117,7 +117,7 @@ describe('AppChrome', () => { }); it('should focus the skip link on initial tab before carrying on with normal tab order', async () => { - setup(Children); + setup(Children, false); await userEvent.keyboard('{tab}'); const skipLink = await screen.findByRole('link', { name: 'Skip to main content' }); expect(skipLink).toHaveFocus(); diff --git a/public/app/core/components/AppChrome/AppChrome.tsx b/public/app/core/components/AppChrome/AppChrome.tsx index 5f7bc35fe96..9ad4d878625 100644 --- a/public/app/core/components/AppChrome/AppChrome.tsx +++ b/public/app/core/components/AppChrome/AppChrome.tsx @@ -7,6 +7,7 @@ import { useStyles2, LinkButton, useTheme2 } from '@grafana/ui'; import config from 'app/core/config'; import { useGrafana } from 'app/core/context/GrafanaContext'; import { CommandPalette } from 'app/features/commandPalette/CommandPalette'; +import { useOpspilotMetadata } from 'app/intergral/useOpspilotMetadata'; import { KioskMode } from 'app/types'; import { AppChromeMenu } from './AppChromeMenu'; @@ -17,14 +18,15 @@ import { SectionNav } from './SectionNav/SectionNav'; import { TopSearchBar } from './TopBar/TopSearchBar'; import { TOP_BAR_LEVEL_HEIGHT } from './types'; -export interface Props extends PropsWithChildren<{}> {} +export interface Props extends PropsWithChildren<{hideSearchBar?: boolean}> {} -export function AppChrome({ children }: Props) { +export function AppChrome({ children, hideSearchBar }: Props) { const { chrome } = useGrafana(); const state = chrome.useState(); - const searchBarHidden = state.searchBarHidden || state.kioskMode === KioskMode.TV; + const searchBarHidden = state.searchBarHidden || state.kioskMode === KioskMode.TV || (hideSearchBar ?? true); const theme = useTheme2(); const styles = useStyles2(getStyles); + useOpspilotMetadata(); const contentClass = cx({ [styles.content]: true, diff --git a/public/app/core/components/AppChrome/AppChromeService.tsx b/public/app/core/components/AppChrome/AppChromeService.tsx index a7a89bfceb2..3339dceceb9 100644 --- a/public/app/core/components/AppChrome/AppChromeService.tsx +++ b/public/app/core/components/AppChrome/AppChromeService.tsx @@ -141,6 +141,8 @@ export class AppChromeService { this.update({ kioskMode: KioskMode.TV }); break; case '1': + case 'embed': + this.update({kioskMode: KioskMode.Embed }); case true: this.update({ kioskMode: KioskMode.Full }); } @@ -150,6 +152,8 @@ export class AppChromeService { switch (mode) { case KioskMode.TV: return 'tv'; + case KioskMode.Embed: + return 'embed'; case KioskMode.Full: return true; default: diff --git a/public/app/core/components/AppChrome/NavToolbar/NavToolbar.tsx b/public/app/core/components/AppChrome/NavToolbar/NavToolbar.tsx index 5d388544308..772ad66c44b 100644 --- a/public/app/core/components/AppChrome/NavToolbar/NavToolbar.tsx +++ b/public/app/core/components/AppChrome/NavToolbar/NavToolbar.tsx @@ -58,21 +58,6 @@ export function NavToolbar({ return (
-
- -
{actions} diff --git a/public/app/core/components/Footer/Footer.tsx b/public/app/core/components/Footer/Footer.tsx index 62739518c0c..66ce8f69738 100644 --- a/public/app/core/components/Footer/Footer.tsx +++ b/public/app/core/components/Footer/Footer.tsx @@ -99,21 +99,7 @@ export interface Props { } export const Footer = React.memo(({ customLinks, hideEdition }: Props) => { - const links = (customLinks || getFooterLinks()).concat(getVersionLinks(hideEdition)); - - return ( -
-
-
    - {links.map((link) => ( -
  • - -
  • - ))} -
-
-
- ); + return
; }); Footer.displayName = 'Footer'; diff --git a/public/app/core/navigation/kiosk.ts b/public/app/core/navigation/kiosk.ts index 64452c4265a..67332cc99ee 100644 --- a/public/app/core/navigation/kiosk.ts +++ b/public/app/core/navigation/kiosk.ts @@ -1,17 +1,33 @@ import { UrlQueryMap } from '@grafana/data'; import { KioskMode } from '../../types'; +import config from '../config'; // TODO Remove after topnav feature toggle is permanent and old NavBar is removed export function getKioskMode(queryParams: UrlQueryMap): KioskMode | null { - switch (queryParams.kiosk) { - case 'tv': - return KioskMode.TV; - // legacy support - case '1': - case true: - return KioskMode.Full; - default: - return null; + if (config.kioskMode === 'off') { + switch (queryParams.kiosk) { + case 'tv': + return KioskMode.TV; + // legacy support + case '1': + case 'full': + case true: + return KioskMode.Full; + case 'embed': + return KioskMode.Embed; + default: + return null; + } + } else { + switch (config.kioskMode) { + // legacy support + case 'full': + return KioskMode.Full; + case 'embed': + return KioskMode.Embed; + default: + return null; + } } } diff --git a/public/app/features/commandPalette/actions/staticActions.ts b/public/app/features/commandPalette/actions/staticActions.ts index d7dd4abd953..1c6dd39ce40 100644 --- a/public/app/features/commandPalette/actions/staticActions.ts +++ b/public/app/features/commandPalette/actions/staticActions.ts @@ -86,5 +86,5 @@ export default (navBarTree: NavModelItem[]): CommandPaletteAction[] => { const navBarActions = navTreeToActions(navBarTree); - return [...globalActions, ...navBarActions]; + return [...navBarActions]; }; diff --git a/public/app/features/dashboard/components/DashNav/DashNav.tsx b/public/app/features/dashboard/components/DashNav/DashNav.tsx index 0f78422beaf..657313c19a4 100644 --- a/public/app/features/dashboard/components/DashNav/DashNav.tsx +++ b/public/app/features/dashboard/components/DashNav/DashNav.tsx @@ -169,7 +169,7 @@ export const DashNav = React.memo((props) => { const { canStar, canShare, isStarred } = dashboard.meta; const buttons: ReactNode[] = []; - if (kioskMode || isPlaylistRunning()) { + if ((kioskMode && kioskMode !== KioskMode.Embed) || isPlaylistRunning()) { return []; } diff --git a/public/app/features/dashboard/containers/DashboardPage.tsx b/public/app/features/dashboard/containers/DashboardPage.tsx index 8770bdec767..6de4bbb2e0d 100644 --- a/public/app/features/dashboard/containers/DashboardPage.tsx +++ b/public/app/features/dashboard/containers/DashboardPage.tsx @@ -321,9 +321,9 @@ export class UnthemedDashboardPage extends PureComponent { } const inspectPanel = this.getInspectPanel(); - const showSubMenu = !editPanel && !kioskMode && !this.props.queryParams.editview; + const showSubMenu = !editPanel && (!kioskMode || kioskMode === KioskMode.Embed) && !this.props.queryParams.editview; - const showToolbar = kioskMode !== KioskMode.Full && !queryParams.editview; + const showToolbar = kioskMode !== KioskMode.Full && !queryParams.editview; const pageClassName = cx({ 'panel-in-fullscreen': Boolean(viewPanel), diff --git a/public/app/features/explore/TraceView/components/TracePageHeader/Actions/TracePageActions.tsx b/public/app/features/explore/TraceView/components/TracePageHeader/Actions/TracePageActions.tsx index d71b4977ce0..2701d5208a5 100644 --- a/public/app/features/explore/TraceView/components/TracePageHeader/Actions/TracePageActions.tsx +++ b/public/app/features/explore/TraceView/components/TracePageHeader/Actions/TracePageActions.tsx @@ -62,15 +62,6 @@ export default function TracePageActions(props: TracePageActionsProps) { return (
- - Give feedback - {
{links?.map((link, i) => ( - + {link.title === "OpsPilot AI" ? : } ))}
diff --git a/public/app/features/templating/template_srv.ts b/public/app/features/templating/template_srv.ts index a255e9384ae..d528de28589 100644 --- a/public/app/features/templating/template_srv.ts +++ b/public/app/features/templating/template_srv.ts @@ -145,7 +145,7 @@ export class TemplateSrv implements BaseTemplateSrv { for (const variable of this.getAdHocVariables()) { const variableUid = variable.datasource?.uid; - if (variableUid === ds.uid) { + if (variableUid === ds.uid || variableUid === ds.name) { filters = filters.concat(variable.filters); } else if (variableUid?.indexOf('$') === 0) { if (this.replace(variableUid) === ds.uid) { diff --git a/public/app/intergral/OpspilotDataLinkButton.tsx b/public/app/intergral/OpspilotDataLinkButton.tsx new file mode 100644 index 00000000000..68b6b2036b2 --- /dev/null +++ b/public/app/intergral/OpspilotDataLinkButton.tsx @@ -0,0 +1,30 @@ +import React from 'react'; + +import { ButtonProps, Button } from '@grafana/ui'; + +type DataLinkButtonProps = { + link: any; + buttonProps?: ButtonProps; +}; + +/** + * @internal + */ +export function OpspilotDataLinkButton({ link, buttonProps }: DataLinkButtonProps) { + return ( + + ); +} diff --git a/public/app/intergral/useOpspilotMetadata.ts b/public/app/intergral/useOpspilotMetadata.ts new file mode 100644 index 00000000000..b8478bb4cae --- /dev/null +++ b/public/app/intergral/useOpspilotMetadata.ts @@ -0,0 +1,24 @@ +import { useEffect } from 'react'; + +import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv'; + + +export const useOpspilotMetadata = () => { + useEffect(() => { + const event = async (event: MessageEvent) => { + if (event.data.type === 'opspilot-host.getMetadata') { + window.parent.postMessage({type: "opspilot-slave.sendMetadata", metadata: { + slaveUrl: window.location.pathname, + timeStart: getTimeSrv().timeRange().from.valueOf(), + timeEnd: getTimeSrv().timeRange().to.valueOf(), + timezone: getTimeSrv().timeModel?.getTimezone() === 'browser' ? Intl.DateTimeFormat().resolvedOptions().timeZone : getTimeSrv().timeModel?.getTimezone(), + } }, '*'); + } + }; + window.addEventListener('message', event); + return () => { + window.removeEventListener('message', event); + } + }, []); + +} diff --git a/public/app/plugins/datasource/grafana/components/QueryEditor.tsx b/public/app/plugins/datasource/grafana/components/QueryEditor.tsx index 4cdac71cc0f..57a1ef9e3f4 100644 --- a/public/app/plugins/datasource/grafana/components/QueryEditor.tsx +++ b/public/app/plugins/datasource/grafana/components/QueryEditor.tsx @@ -53,21 +53,11 @@ export class UnthemedQueryEditor extends PureComponent { state: State = { channels: [], channelFields: {} }; queryTypes: Array> = [ - { - label: 'Random Walk', - value: GrafanaQueryType.RandomWalk, - description: 'Random signal within the selected time range', - }, { label: 'Live Measurements', value: GrafanaQueryType.LiveMeasurements, description: 'Stream real-time measurements from Grafana', }, - { - label: 'List public files', - value: GrafanaQueryType.List, - description: 'Show directory listings for public resources', - }, ]; constructor(props: Props) { @@ -495,11 +485,6 @@ export class UnthemedQueryEditor extends PureComponent { {queryType === GrafanaQueryType.LiveMeasurements && this.renderMeasurementsQuery()} - {queryType === GrafanaQueryType.List && this.renderListPublicFiles()} - {queryType === GrafanaQueryType.Snapshot && this.renderSnapshotQuery()} - {queryType === GrafanaQueryType.Search && ( - - )} ); } diff --git a/public/app/types/dashboard.ts b/public/app/types/dashboard.ts index 8a37867ab97..df9f732e879 100644 --- a/public/app/types/dashboard.ts +++ b/public/app/types/dashboard.ts @@ -96,6 +96,7 @@ export interface DashboardInitError { export enum KioskMode { TV = 'tv', Full = 'full', + Embed = 'embed', } export type GetMutableDashboardModelFn = () => DashboardModel | null;