fix: show api url in main settings (#4896)
# What this PR does - show api_url from GET /status endpoint on settings page - refactor MainSettings to be functional component ## Which issue(s) this PR closes https://raintank-corp.slack.com/archives/C0713BYQB0W/p1724249719392329 <!-- *Note*: If you want the issue to be auto-closed once the PR is merged, change "Related to" to "Closes" in the line above. If you have more than one GitHub issue that this PR closes, be sure to preface each issue link with a [closing keyword](https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/using-keywords-in-issues-and-pull-requests#linking-a-pull-request-to-an-issue). This ensures that the issue(s) are auto-closed once the PR has been merged. --> ## Checklist - [ ] Unit, integration, and e2e (if applicable) tests updated - [x] Documentation added (or `pr:no public docs` PR label added if not required) - [x] Added the relevant release notes label (see labels prefixed w/ `release:`). These labels dictate how your PR will show up in the autogenerated release notes.
This commit is contained in:
parent
070abb9d4f
commit
b5c52255d5
7 changed files with 72 additions and 107 deletions
|
|
@ -120,7 +120,7 @@ export const ApiTokenForm = observer((props: TokenCreationModalProps) => {
|
|||
<VerticalGroup>
|
||||
<Label>Curl command example</Label>
|
||||
<SourceCode noMinHeight showClipboardIconOnly>
|
||||
{getCurlExample(token, store.onCallApiUrl)}
|
||||
{getCurlExample(token, store.pluginStore.apiUrlFromStatus)}
|
||||
</SourceCode>
|
||||
</VerticalGroup>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { OnCallPluginMetaJSONData } from 'types';
|
|||
import { ActionKey } from 'models/loader/action-keys';
|
||||
import { GrafanaApiClient } from 'network/grafana-api/http-client';
|
||||
import { makeRequest } from 'network/network';
|
||||
import { PluginConnection, PostStatusResponse } from 'network/oncall-api/api.types';
|
||||
import { PluginConnection, StatusResponse } from 'network/oncall-api/api.types';
|
||||
import { RootBaseStore } from 'state/rootBaseStore/RootBaseStore';
|
||||
import { waitInMs } from 'utils/async';
|
||||
import { AutoLoadingState } from 'utils/decorators';
|
||||
|
|
@ -31,6 +31,7 @@ On Cloud:
|
|||
export class PluginStore {
|
||||
rootStore: RootBaseStore;
|
||||
connectionStatus?: PluginConnection;
|
||||
apiUrlFromStatus?: string;
|
||||
isPluginConnected = false;
|
||||
appliedOnCallApiUrl = '';
|
||||
|
||||
|
|
@ -53,9 +54,10 @@ export class PluginStore {
|
|||
|
||||
@AutoLoadingState(ActionKey.PLUGIN_VERIFY_CONNECTION)
|
||||
async verifyPluginConnection() {
|
||||
const { pluginConnection } = await makeRequest<PostStatusResponse>(`/plugin/status`, {});
|
||||
const { pluginConnection, api_url } = await makeRequest<StatusResponse>(`/plugin/status`, {});
|
||||
runInAction(() => {
|
||||
this.connectionStatus = pluginConnection;
|
||||
this.apiUrlFromStatus = api_url;
|
||||
this.isPluginConnected = Object.keys(pluginConnection).every(
|
||||
(key) => pluginConnection[key as keyof PluginConnection]?.ok
|
||||
);
|
||||
|
|
|
|||
|
|
@ -16,15 +16,10 @@ type PluginConnection = {
|
|||
grafana_url_from_engine: PluginConnectionCheck;
|
||||
};
|
||||
|
||||
export type PostStatusResponse = {
|
||||
export type StatusResponse = {
|
||||
pluginConnection: PluginConnection;
|
||||
allow_signup: boolean;
|
||||
api_url: string;
|
||||
currently_undergoing_maintenance_message: string | null;
|
||||
is_installed: boolean;
|
||||
is_user_anonymous: boolean;
|
||||
license: string;
|
||||
recaptcha_site_key: string;
|
||||
token_ok: boolean;
|
||||
version: string;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,7 +0,0 @@
|
|||
.title {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.settings {
|
||||
width: fit-content;
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react';
|
||||
|
||||
import { Field, Input, Switch } from '@grafana/ui';
|
||||
import cn from 'classnames/bind';
|
||||
import { css } from '@emotion/css';
|
||||
import { Field, Input, Switch, useStyles2 } from '@grafana/ui';
|
||||
import { observer } from 'mobx-react';
|
||||
import { LegacyNavHeading } from 'navbar/LegacyNavHeading';
|
||||
|
||||
|
|
@ -10,86 +10,71 @@ import { ApiTokenSettings } from 'containers/ApiTokenSettings/ApiTokenSettings';
|
|||
import { WithPermissionControlTooltip } from 'containers/WithPermissionControl/WithPermissionControlTooltip';
|
||||
import { TeamsSettings } from 'pages/settings/tabs/TeamsSettings/TeamsSettings';
|
||||
import { isTopNavbar } from 'plugin/GrafanaPluginRootPage.helpers';
|
||||
import { WithStoreProps } from 'state/types';
|
||||
import { withMobXProviderContext } from 'state/withStore';
|
||||
import { useStore } from 'state/useStore';
|
||||
import { UserActions } from 'utils/authorization/authorization';
|
||||
|
||||
import styles from './MainSettings.module.css';
|
||||
export const MainSettings = observer(() => {
|
||||
const styles = useStyles2(getStyles);
|
||||
const {
|
||||
organizationStore: { currentOrganization, saveCurrentOrganization },
|
||||
pluginStore: { apiUrlFromStatus },
|
||||
} = useStore();
|
||||
|
||||
const cx = cn.bind(styles);
|
||||
|
||||
interface SettingsPageProps extends WithStoreProps {}
|
||||
|
||||
interface SettingsPageState {
|
||||
apiUrl?: string;
|
||||
}
|
||||
|
||||
@observer
|
||||
class Settings extends React.Component<SettingsPageProps, SettingsPageState> {
|
||||
state: SettingsPageState = {
|
||||
apiUrl: '',
|
||||
};
|
||||
|
||||
async componentDidMount() {
|
||||
const { store } = this.props;
|
||||
const url = await store.getApiUrlForSettings();
|
||||
this.setState({ apiUrl: url });
|
||||
}
|
||||
|
||||
render() {
|
||||
const { organizationStore } = this.props.store;
|
||||
const { currentOrganization } = organizationStore;
|
||||
const { apiUrl } = this.state;
|
||||
|
||||
return (
|
||||
<div className={cx('root')}>
|
||||
<LegacyNavHeading>
|
||||
<Text.Title level={3} className={cx('title')}>
|
||||
Organization settings
|
||||
</Text.Title>
|
||||
</LegacyNavHeading>
|
||||
|
||||
<div className={cx('settings')}>
|
||||
<Text.Title level={3} className={cx('title')}>
|
||||
Resolution Note
|
||||
</Text.Title>
|
||||
<Field
|
||||
loading={!currentOrganization}
|
||||
label="Require a resolution note when resolving Alert Groups"
|
||||
description={`Once user clicks "Resolve" for an Alert Group, they will be required to fill in a resolution note about the Alert Group`}
|
||||
>
|
||||
<WithPermissionControlTooltip userAction={UserActions.OtherSettingsWrite}>
|
||||
<Switch
|
||||
value={currentOrganization?.is_resolution_note_required}
|
||||
onChange={(event) => {
|
||||
organizationStore.saveCurrentOrganization({
|
||||
is_resolution_note_required: event.currentTarget.checked,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</WithPermissionControlTooltip>
|
||||
</Field>
|
||||
</div>
|
||||
{!isTopNavbar() && (
|
||||
<div style={{ marginBottom: '20px' }}>
|
||||
<Text.Title level={3} className={cx('title')}>
|
||||
Teams and Access Settings
|
||||
</Text.Title>
|
||||
<TeamsSettings />
|
||||
</div>
|
||||
)}
|
||||
<Text.Title level={3} className={cx('title')}>
|
||||
API URL
|
||||
return (
|
||||
<div>
|
||||
<LegacyNavHeading>
|
||||
<Text.Title level={3} className={styles.title}>
|
||||
Organization settings
|
||||
</Text.Title>
|
||||
<div>
|
||||
<Field>
|
||||
<Input value={apiUrl} disabled />
|
||||
</Field>
|
||||
</div>
|
||||
<ApiTokenSettings />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
</LegacyNavHeading>
|
||||
|
||||
export const MainSettings = withMobXProviderContext(Settings);
|
||||
<div className={styles.settings}>
|
||||
<Text.Title level={3} className={styles.title}>
|
||||
Resolution Note
|
||||
</Text.Title>
|
||||
<Field
|
||||
loading={!currentOrganization}
|
||||
label="Require a resolution note when resolving Alert Groups"
|
||||
description={`Once user clicks "Resolve" for an Alert Group, they will be required to fill in a resolution note about the Alert Group`}
|
||||
>
|
||||
<WithPermissionControlTooltip userAction={UserActions.OtherSettingsWrite}>
|
||||
<Switch
|
||||
value={currentOrganization?.is_resolution_note_required}
|
||||
onChange={(event) => {
|
||||
saveCurrentOrganization({
|
||||
is_resolution_note_required: event.currentTarget.checked,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</WithPermissionControlTooltip>
|
||||
</Field>
|
||||
</div>
|
||||
{!isTopNavbar() && (
|
||||
<div style={{ marginBottom: '20px' }}>
|
||||
<Text.Title level={3} className={styles.title}>
|
||||
Teams and Access Settings
|
||||
</Text.Title>
|
||||
<TeamsSettings />
|
||||
</div>
|
||||
)}
|
||||
<Text.Title level={3} className={styles.title}>
|
||||
API URL
|
||||
</Text.Title>
|
||||
<div>
|
||||
<Field>
|
||||
<Input value={apiUrlFromStatus} disabled />
|
||||
</Field>
|
||||
</div>
|
||||
<ApiTokenSettings />
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
const getStyles = () => ({
|
||||
settings: css`
|
||||
width: fit-content;
|
||||
`,
|
||||
title: css`
|
||||
margin-bottom: 20px;
|
||||
`,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -69,9 +69,6 @@ export class RootBaseStore {
|
|||
@observable
|
||||
pageTitle = '';
|
||||
|
||||
@observable
|
||||
onCallApiUrl: string;
|
||||
|
||||
@observable
|
||||
insightsDatasource = 'grafanacloud-usage';
|
||||
|
||||
|
|
@ -186,11 +183,6 @@ export class RootBaseStore {
|
|||
this.pageTitle = title;
|
||||
}
|
||||
|
||||
@action.bound
|
||||
async getApiUrlForSettings() {
|
||||
return this.onCallApiUrl;
|
||||
}
|
||||
|
||||
@action.bound
|
||||
async loadRecaptcha() {
|
||||
const { recaptcha_site_key } = await makeRequest<{ recaptcha_site_key: string }>('/plugin/recaptcha');
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { AppRootProps as BaseAppRootProps, AppPluginMeta, PluginConfigPageProps, BootData } from '@grafana/data';
|
||||
import { AppRootProps as BaseAppRootProps, AppPluginMeta, PluginConfigPageProps } from '@grafana/data';
|
||||
|
||||
import { getPluginId } from 'utils/consts';
|
||||
|
||||
|
|
@ -30,8 +30,6 @@ export type OnCallPluginExtensionPoints =
|
|||
|
||||
declare global {
|
||||
export interface Window {
|
||||
// https://github.com/grafana/grafana/blob/78bef7a26a799209b5307d6bde8e25fcb4fbde7d/public/views/index-template.html#L251-L258
|
||||
grafanaBootData?: BootData;
|
||||
RECAPTCHA_SITE_KEY: string;
|
||||
grecaptcha: any;
|
||||
dataLayer: any;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue