Skip to content

Commit

Permalink
extract min refresh to settings
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewazores committed Feb 7, 2023
1 parent f7c40e0 commit e96a664
Show file tree
Hide file tree
Showing 9 changed files with 143 additions and 7 deletions.
5 changes: 5 additions & 0 deletions locales/en/public.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@
"LANGUAGE_REGION": "Language & Region",
"NOTIFICATION_MESSAGE": "Notifications & Messages"
},
"CHARTS_CONFIG": {
"DESCRIPTION": "Set configuration options for the behaviour of Metrics cards on the Dashboard.",
"REFRESH_RATE_SETTING": "Configure the minimum time to wait between data refreshes. Individual metrics cards may still request updates on a faster cycle, but the client application instance will throttle update requests to the server according to this setting.",
"TITLE": "Dashboard Metrics Configuration"
},
"CREDENTIALS_STORAGE": {
"BACKEND": {
"DESCRIPTION": "Keep credentials in encrypted Cryostat backend storage. These credentials will be available to other users and will be used for Automated Rules.",
Expand Down
7 changes: 6 additions & 1 deletion src/app/Dashboard/Charts/ChartContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,12 @@ export interface Controllers {
}

const ChartContext: React.Context<Controllers> = React.createContext({
controller: new ChartController(defaultServices.api, defaultServices.target, defaultServices.notificationChannel),
controller: new ChartController(
defaultServices.api,
defaultServices.target,
defaultServices.notificationChannel,
defaultServices.settings
),
});

export { ChartContext };
9 changes: 4 additions & 5 deletions src/app/Dashboard/Charts/ChartController.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@

import { ApiService } from '@app/Shared/Services/Api.service';
import { NotificationCategory, NotificationChannel } from '@app/Shared/Services/NotificationChannel.service';
import { SettingsService } from '@app/Shared/Services/Settings.service';
import { NO_TARGET, Target, TargetService } from '@app/Shared/Services/Target.service';
import {
BehaviorSubject,
Expand All @@ -58,9 +59,6 @@ import {

export const RECORDING_NAME = 'dashboard_metrics';

// TODO make this configurable
export const MIN_REFRESH = 10_000;

export class ChartController {
private readonly _refCount$ = new BehaviorSubject<number>(0);
private readonly _updates$ = new ReplaySubject<void>(1);
Expand All @@ -70,7 +68,8 @@ export class ChartController {
constructor(
private readonly _api: ApiService,
private readonly _target: TargetService,
private readonly _notifications: NotificationChannel
private readonly _notifications: NotificationChannel,
private readonly _settings: SettingsService
) {
this._subscriptions.push(
this._refCount$
Expand Down Expand Up @@ -148,7 +147,7 @@ export class ChartController {
this._subscriptions.push(
merge(
merge(
this._updates$.pipe(throttleTime(MIN_REFRESH)),
this._updates$.pipe(throttleTime(this._settings.chartControllerConfig().minRefresh)),
this._notifications.messages(NotificationCategory.ActiveRecordingCreated),
this._notifications.messages(NotificationCategory.ActiveRecordingDeleted),
this._notifications.messages(NotificationCategory.ActiveRecordingStopped)
Expand Down
7 changes: 6 additions & 1 deletion src/app/Dashboard/Dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,12 @@ export const Dashboard: React.FC<DashboardProps> = (_) => {
const dispatch = useDispatch<StateDispatch>();
const cardConfigs: CardConfig[] = useSelector((state: RootState) => state.dashboardConfigs.list);
const chartController = React.useRef(
new ChartController(serviceContext.api, serviceContext.target, serviceContext.notificationChannel)
new ChartController(
serviceContext.api,
serviceContext.target,
serviceContext.notificationChannel,
serviceContext.settings
)
);

React.useEffect(() => {
Expand Down
108 changes: 108 additions & 0 deletions src/app/Settings/ChartCardsConfig.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/*
* Copyright The Cryostat Authors
*
* The Universal Permissive License (UPL), Version 1.0
*
* Subject to the condition set forth below, permission is hereby granted to any
* person obtaining a copy of this software, associated documentation and/or data
* (collectively the "Software"), free of charge and under any and all copyright
* rights in the Software, and any and all patent rights owned or freely
* licensable by each licensor hereunder covering either (i) the unmodified
* Software as contributed to or provided by such licensor, or (ii) the Larger
* Works (as defined below), to deal in both
*
* (a) the Software, and
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
* one is included with the Software (each a "Larger Work" to which the Software
* is contributed by such licensors),
*
* without restriction, including without limitation the rights to copy, create
* derivative works of, display, perform, and distribute the Software and make,
* use, sell, offer for sale, import, export, have made, and have sold the
* Software and the Larger Work(s), and to sublicense the foregoing rights on
* either these or other terms.
*
* This license is subject to the following condition:
* The above copyright notice and either this complete permission notice or at
* a minimum a reference to the UPL must be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

import { ServiceContext } from '@app/Shared/Services/Services';
import { FormGroup, HelperText, HelperTextItem, NumberInput, Stack, StackItem } from '@patternfly/react-core';
import * as React from 'react';
import { useTranslation } from 'react-i18next';
import { UserSetting } from './Settings';

const min = 1;

const Component = () => {
const [t] = useTranslation();
const context = React.useContext(ServiceContext);

const [minRefresh, setMinRefresh] = React.useState(context.settings.chartControllerConfig().minRefresh);

const handleChange = React.useCallback(
(evt) => {
let value = isNaN(evt.target.value) ? minRefresh : Number(evt.target.value);
if (value < min) {
value = min;
}
setMinRefresh(value);
context.settings.setChartControllerConfig({ minRefresh: value });
},
[minRefresh, setMinRefresh, context.settings]
);

const handleVisibleStep = React.useCallback(
(delta: number) => () => {
const v = minRefresh + delta;
context.settings.setChartControllerConfig({ minRefresh: v });
},
[minRefresh, context.settings]
);

return (
<Stack hasGutter>
<StackItem>
<FormGroup>
<HelperText>
<HelperTextItem>{t('SETTINGS.CHARTS_CONFIG.REFRESH_RATE_SETTING')}</HelperTextItem>
</HelperText>
<NumberInput
inputName="minRefresh"
value={minRefresh}
min={min}
onChange={handleChange}
onMinus={handleVisibleStep(-1)}
onPlus={handleVisibleStep(1)}
unit={t('SECOND', { ns: 'common' })}
/>
</FormGroup>
</StackItem>
</Stack>
);
};

export const ChartCardsConfig: UserSetting = {
titleKey: 'SETTINGS.CHARTS_CONFIG.TITLE',
descConstruct: 'SETTINGS.CHARTS_CONFIG.DESCRIPTION',
content: Component,
category: 'SETTINGS.CATEGORIES.DASHBOARD',
};

export interface ChartControllerConfig {
minRefresh: number;
}

export const defaultChartControllerConfig: ChartControllerConfig = {
minRefresh: 10,
};
2 changes: 2 additions & 0 deletions src/app/Settings/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ import { Trans, useTranslation } from 'react-i18next';
import { useLocation } from 'react-router-dom';
import { AutomatedAnalysisConfig } from './AutomatedAnalysisConfig';
import { AutoRefresh } from './AutoRefresh';
import { ChartCardsConfig } from './ChartCardsConfig';
import { CredentialsStorage } from './CredentialsStorage';
import { DatetimeControl } from './DatetimeControl';
import { DeletionDialogControl } from './DeletionDialogControl';
Expand Down Expand Up @@ -136,6 +137,7 @@ export const Settings: React.FC<SettingsProps> = (_) => {
[
NotificationControl,
AutomatedAnalysisConfig,
ChartCardsConfig,
CredentialsStorage,
DeletionDialogControl,
WebSocketDebounce,
Expand Down
2 changes: 2 additions & 0 deletions src/app/Settings/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
/**
* t('SETTINGS.AUTOMATED_ANALYSIS_CONFIG.TITLE')
* t('SETTINGS.AUTOMATED_ANALYSIS_CONFIG.DESCRIPTION')
* t('SETTINGS.CHARTS_CONFIG.TITLE')
* t('SETTINGS.CHARTS_CONFIG.DESCRIPTION')
* t('SETTINGS.AUTO_REFRESH.TITLE')
* t('SETTINGS.AUTO_REFRESH.DESCRIPTION')
* t('SETTINGS.CREDENTIALS_STORAGE.TITLE')
Expand Down
9 changes: 9 additions & 0 deletions src/app/Shared/Services/Settings.service.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
*/

import { DeleteOrDisableWarningType } from '@app/Modal/DeleteWarningUtils';
import { ChartControllerConfig, defaultChartControllerConfig } from '@app/Settings/ChartCardsConfig';
import { getFromLocalStorage, saveToLocalStorage } from '@app/utils/LocalStorage';
import { DatetimeFormat, defaultDatetimeFormat } from '@i18n/datetime';
import { BehaviorSubject, Observable } from 'rxjs';
Expand Down Expand Up @@ -146,6 +147,14 @@ export class SettingsService {
saveToLocalStorage('AUTOMATED_ANALYSIS_RECORDING_CONFIG', config);
}

chartControllerConfig(defaultConfig = defaultChartControllerConfig): ChartControllerConfig {
return getFromLocalStorage('CHART_CONTROLLER_CONFIG', defaultConfig);
}

setChartControllerConfig(config: ChartControllerConfig): void {
saveToLocalStorage('CHART_CONTROLLER_CONFIG', config);
}

deletionDialogsEnabled(): Map<DeleteOrDisableWarningType, boolean> {
const value = getFromLocalStorage('DELETION_DIALOGS_ENABLED', undefined);
if (typeof value === 'object') {
Expand Down
1 change: 1 addition & 0 deletions src/app/utils/LocalStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export enum LocalStorageKey {
AUTO_REFRESH_PERIOD,
AUTO_REFRESH_UNITS,
AUTOMATED_ANALYSIS_RECORDING_CONFIG,
CHART_CONTROLLER_CONFIG,
DELETION_DIALOGS_ENABLED,
VISIBLE_NOTIFICATIONS_COUNT,
NOTIFICATIONS_ENABLED,
Expand Down

0 comments on commit e96a664

Please sign in to comment.