Skip to content

Commit

Permalink
frontend: PluginSettings: Refactor local storage and plugin data
Browse files Browse the repository at this point in the history
Signed-off-by: Vincent T <[email protected]>
  • Loading branch information
vyncent-t committed Dec 12, 2024
1 parent d0eea72 commit d2f8668
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 13 deletions.
52 changes: 48 additions & 4 deletions frontend/src/components/App/PluginSettings/PluginSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ const EnableSwitch = (props: SwitchProps) => {
/** PluginSettingsPure is the main component to where we render the plugin data. */
export function PluginSettingsPure(props: PluginSettingsPureProps) {
const { t } = useTranslation(['translation']);
const dispatch = useDispatch();

/** Plugin arr to be rendered to the page from prop data */
const pluginArr: any = props.plugins ? props.plugins : [];
Expand All @@ -118,6 +119,49 @@ export function PluginSettingsPure(props: PluginSettingsPureProps) {
})
);

/**
* This is the name and isEnabled parts from the plugin JSON data that is saved in local storage
*/
const [pluginsEnabledSettings, setPluginsEnabledSettings] = useState<any>(
useTypedSelector(state => state.plugins?.pluginSettings)
);

/**
* If there are no settings to be saved on local storage, then the default isEnabled from the plugins settings are saved.
*/
if (pluginsEnabledSettings.length === 0) {
storeEnableSettings();
}

/**
* Handles backwards compatible by checkiing if the number of keys in pluginsEnabledSettings is more thant 3 (i,e more than name, isEnabled )
*/
if (Object.keys(pluginsEnabledSettings[0]).length > 3) {
const backwardsCompatible = pluginsEnabledSettings.map((plugin: any) => {
return {
name: plugin.name,
isEnabled: plugin.isEnabled,
};
});
setPluginsEnabledSettings(backwardsCompatible);
dispatch(setPluginSettings(backwardsCompatible));
}

/**
* This function is what trims the JSON data for the plugin into a smaller object to be used in local storage
*/
function storeEnableSettings() {
const pendingSettings = pluginChanges.map((plugin: PluginInfo) => {
return {
name: plugin.name,
isEnabled: plugin.isEnabled,
};
});

setPluginsEnabledSettings(pendingSettings);
dispatch(setPluginSettings(pendingSettings));
}

/**
* useEffect to control the rendering of the save button.
* By default, the enableSave is set to false.
Expand Down Expand Up @@ -154,6 +198,7 @@ export function PluginSettingsPure(props: PluginSettingsPureProps) {
* This function then takes the current state of the pluginChanges array and inputs it to the onSave prop function.
*/
function onSaveButtonHandler() {
storeEnableSettings();
props.onSave(pluginChanges);
}

Expand Down Expand Up @@ -283,13 +328,12 @@ export function PluginSettingsPure(props: PluginSettingsPureProps) {
export default function PluginSettings() {
const dispatch = useDispatch();

const pluginSettings = useTypedSelector(state => state.plugins.pluginSettings);
const pluginData = useTypedSelector(state => state.plugins.pluginData);

return (
<PluginSettingsPure
plugins={pluginSettings}
onSave={plugins => {
dispatch(setPluginSettings(plugins));
plugins={pluginData}
onSave={() => {
dispatch(reloadPage());
}}
/>
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/plugin/Plugins.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import helpers from '../helpers';
import { UI_INITIALIZE_PLUGIN_VIEWS } from '../redux/actions/actions';
import { useTypedSelector } from '../redux/reducers/reducers';
import { fetchAndExecutePlugins } from './index';
import { pluginsLoaded, setPluginSettings } from './pluginsSlice';
import { pluginsLoaded, setPluginData } from './pluginsSlice';

/**
* For discovering and executing plugins.
Expand All @@ -35,7 +35,7 @@ export default function Plugins() {
fetchAndExecutePlugins(
settingsPlugins,
updatedSettingsPackages => {
dispatch(setPluginSettings(updatedSettingsPackages));
dispatch(setPluginData(updatedSettingsPackages));
},
incompatiblePlugins => {
const pluginList = Object.values(incompatiblePlugins)
Expand Down
10 changes: 6 additions & 4 deletions frontend/src/plugin/pluginSlice.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ const initialState: PluginsState = {
loaded: false,
/** If plugin settings are saved use those. */
pluginSettings: JSON.parse(localStorage.getItem('headlampPluginSettings') || '[]'),
/** Information stored by settings about plugins. */
pluginData: [],
};

// Mock React component for testing
Expand All @@ -24,7 +26,7 @@ describe('pluginsSlice reducers', () => {
const existingPluginName = 'test-plugin';
const initialStateWithPlugin: PluginsState = {
...initialState,
pluginSettings: [
pluginData: [
{
name: existingPluginName,
settingsComponent: undefined,
Expand All @@ -41,15 +43,15 @@ describe('pluginsSlice reducers', () => {

const newState = pluginsSlice.reducer(initialStateWithPlugin, action);

expect(newState.pluginSettings[0].settingsComponent).toBeDefined();
expect(newState.pluginSettings[0].displaySettingsComponentWithSaveButton).toBe(true);
expect(newState.pluginData[0].settingsComponent).toBeDefined();
expect(newState.pluginData[0].displaySettingsComponentWithSaveButton).toBe(true);
});

test('should not modify state when plugin name does not match any existing plugin', () => {
const nonExistingPluginName = 'non-existing-plugin';
const initialStateWithPlugin: PluginsState = {
...initialState,
pluginSettings: [
pluginData: [
{
name: 'existing-plugin',
settingsComponent: undefined,
Expand Down
19 changes: 16 additions & 3 deletions frontend/src/plugin/pluginsSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,16 @@ export interface PluginsState {
loaded: boolean;
/** Information stored by settings about plugins. */
pluginSettings: PluginInfo[];
/** Information stored by settings about plugins. */
pluginData: PluginInfo[];
}
const initialState: PluginsState = {
/** Once the plugins have been fetched and executed. */
loaded: false,
/** If plugin settings are saved use those. */
pluginSettings: JSON.parse(localStorage.getItem('headlampPluginSettings') || '[]'),
/** If plugin data is saved use those. */
pluginData: [],
};

export const pluginsSlice = createSlice({
Expand All @@ -114,6 +118,10 @@ export const pluginsSlice = createSlice({
state.pluginSettings = action.payload;
localStorage.setItem('headlampPluginSettings', JSON.stringify(action.payload));
},
/** Sets the plugin data */
setPluginData(state, action: PayloadAction<PluginInfo[]>) {
state.pluginData = action.payload;
},
/** Reloads the browser page */
reloadPage() {
window.location.reload();
Expand All @@ -130,7 +138,7 @@ export const pluginsSlice = createSlice({
}>
) {
const { name, component, displaySaveButton } = action.payload;
state.pluginSettings = state.pluginSettings.map(plugin => {
state.pluginData = state.pluginData?.map(plugin => {
if (plugin.name === name) {
return {
...plugin,
Expand All @@ -144,7 +152,12 @@ export const pluginsSlice = createSlice({
},
});

export const { pluginsLoaded, setPluginSettings, setPluginSettingsComponent, reloadPage } =
pluginsSlice.actions;
export const {
pluginsLoaded,
setPluginSettings,
setPluginData,
setPluginSettingsComponent,
reloadPage,
} = pluginsSlice.actions;

export default pluginsSlice.reducer;

0 comments on commit d2f8668

Please sign in to comment.