Skip to content

Commit

Permalink
plugins(change-logo): Make the logo configurable
Browse files Browse the repository at this point in the history
this patch adds plugin settings component which
can be used by the user to configure custom
logo by providing the URL.

Signed-off-by: yolossn <[email protected]>
  • Loading branch information
yolossn committed Feb 9, 2024
1 parent 59b4959 commit c42dcdd
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 3 deletions.
17 changes: 14 additions & 3 deletions plugins/examples/change-logo/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@
// import { registerAppLogo } from '@kinvolk/headlamp-plugin/lib';
// registerAppLogo(() => <p>My Logo</p>);

import { AppLogoProps, registerAppLogo } from '@kinvolk/headlamp-plugin/lib';
import {
AppLogoProps,
registerAppLogo,
registerPluginSettings,
} from '@kinvolk/headlamp-plugin/lib';
import { SvgIcon } from '@mui/material';
import LogoWithTextLight from './icon-large-light.svg';
import LogoLight from './icon-small-light.svg';

import Settings, { store } from './settings';
/**
* A simple logo using two different SVG files.
* One for the small logo (used in mobile view), and a larger one used in desktop view.
Expand All @@ -18,7 +22,12 @@ import LogoLight from './icon-small-light.svg';
function SimpleLogo(props: AppLogoProps) {
const { logoType, className } = props;

return (
const useConf = store.useConfig();
const config = useConf();

return config?.url ? (
<img src={config?.url} alt="logo" className={className} />
) : (
<SvgIcon
className={className}
component={logoType === 'large' ? LogoWithTextLight : LogoLight}
Expand Down Expand Up @@ -56,3 +65,5 @@ if (show === 'simple') {
} else {
registerAppLogo(ReactiveLogo);
}

registerPluginSettings('change-logo', Settings, true);
113 changes: 113 additions & 0 deletions plugins/examples/change-logo/src/settings.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import { ConfigStore } from '@kinvolk/headlamp-plugin/lib';
import { NameValueTable } from '@kinvolk/headlamp-plugin/lib/CommonComponents';
import Box from '@mui/material/Box';
import TextField from '@mui/material/TextField';
import { useEffect, useState } from 'react';

/**
* A text input component with auto-save functionality. It debounces the input value changes and triggers the onSave callback after a specified delay, allowing for efficient data saving with minimal performance impact.
*
* @param {Object} props - The component props.
* @param {function(string): void} props.onSave - Callback function to save the value. It receives the current value as its only argument.
* @param {string} [props.defaultValue=''] - The default value of the input.
* @param {number} [props.delay=1000] - The delay in milliseconds before the onSave callback is invoked after the user stops typing.
* @param {string} [props.helperText=''] - Optional helper text to display below the input.
* @returns {JSX.Element} The AutoSaveInput component.
*/
function AutoSaveInput({ onSave, defaultValue = '', delay = 1000, helperText = '' }) {
const [value, setValue] = useState(defaultValue);
const [timer, setTimer] = useState(null);

const handleChange = event => {
const newValue = event.target.value;
setValue(newValue);

if (timer) {
clearTimeout(timer);
}

const newTimer = setTimeout(() => onSave(newValue), delay);
setTimer(newTimer);
};

useEffect(() => {
// Cleanup on unmount
return () => {
if (timer) {
clearTimeout(timer);
}
};
}, [timer]);

return (
<TextField
fullWidth
InputProps={{ style: { borderBottom: '1px solid rgba(0, 0, 0, 0.42)' } }}
InputLabelProps={{
shrink: true,
style: { display: 'none' },
}}
helperText={helperText}
value={value}
onChange={handleChange}
variant="standard"
/>
);
}

interface pluginConfig {
url: string;
}

export const store = new ConfigStore<pluginConfig>('change-logo');

/**
* Settings component for managing plugin configuration details.
* It allows users to update specific configuration properties, such as the logo URL,
* and automatically saves these updates to a persistent store.
*
* @returns {JSX.Element} The rendered settings component with configuration options.
*/
export default function Settings() {
// Retrieve initial configuration from the store
const config = store.get();
// State to manage the current configuration within the component
const [currentConfig, setCurrentConfig] = useState(config);

/**
* Handles saving the updated configuration value to the store.
* It updates the specified configuration property and refreshes the local component state
* to reflect the latest configuration.
*
* @param {string} value - The new value for the configuration property to be updated.
*/
function handleSave(value) {
const updatedConfig = { url: value };
// Save the updated configuration to the store
store.set(updatedConfig);
// Update the component state to reflect the new configuration
setCurrentConfig(store.get());
}

// Define rows for the settings table, including the AutoSaveInput component for the logo URL
const settingsRows = [
{
name: 'Logo URL',
value: (
<AutoSaveInput
defaultValue={currentConfig?.url}
onSave={handleSave}
delay={1000}
helperText={'Enter the URL of your logo.'}
/>
),
},
];

// Render the settings component
return (
<Box width={'80%'} style={{ paddingTop: '8vh' }}>
<NameValueTable rows={settingsRows} />
</Box>
);
}

0 comments on commit c42dcdd

Please sign in to comment.