UserStorage: multiple improvements (#103779)

This commit is contained in:
Andres Martinez Gotor
2025-04-11 11:32:31 +02:00
committed by GitHub
parent 3607356f65
commit 8ebce76535
5 changed files with 33 additions and 10 deletions
@@ -25,3 +25,5 @@ export {
setGetObservablePluginLinks,
type GetObservablePluginLinks,
} from '../services/pluginExtensions/getObservablePluginLinks';
export { UserStorage } from '../utils/userStorage';
@@ -37,6 +37,14 @@ class MyDataSource extends DataSourceWithBackend<MyQuery, DataSourceJsonData> {
applyTemplateVariables(query: MyQuery, scopedVars: ScopedVars, filters?: AdHocVariableFilter[] | undefined): MyQuery {
return { ...query, applyTemplateVariablesCalled: true, filters };
}
async getValue(key: string) {
return await this.userStorage.getItem(key);
}
async setValue(key: string, value: string) {
await this.userStorage.setItem(key, value);
}
}
const mockDatasourceRequest = jest.fn<Promise<FetchResponse>, BackendSrvRequest[]>();
@@ -536,6 +544,15 @@ describe('DataSourceWithBackend', () => {
expect(publicDashboardQueryHandler).toHaveBeenCalledWith(request);
});
});
describe('user storage', () => {
test('sets and gets a value', async () => {
const { ds } = createMockDatasource();
await ds.setValue('multiplier', '1');
expect(await ds.getValue('multiplier')).toBe('1');
});
});
});
function createMockDatasource() {
@@ -34,6 +34,7 @@ import {
import { publicDashboardQueryHandler } from './publicDashboardQueryHandler';
import { BackendDataSourceResponse, toDataQueryResponse } from './queryResponse';
import { UserStorage } from './userStorage';
/**
* @internal
@@ -121,8 +122,11 @@ class DataSourceWithBackend<
TQuery extends DataQuery = DataQuery,
TOptions extends DataSourceJsonData = DataSourceJsonData,
> extends DataSourceApi<TQuery, TOptions> {
protected userStorage: UserStorage;
constructor(instanceSettings: DataSourceInstanceSettings<TOptions>) {
super(instanceSettings);
this.userStorage = new UserStorage(instanceSettings.type);
}
/**
@@ -48,15 +48,15 @@ describe('userStorage', () => {
it('use localStorage if the user is not logged in', async () => {
config.bootData.user.isSignedIn = false;
const storage = usePluginUserStorage();
storage.getItem('key');
expect(localStorage.getItem).toHaveBeenCalled();
await storage.getItem('key');
expect(localStorage.getItem).toHaveBeenCalledWith('plugin-id:abc:key');
});
it('use localStorage if the user storage is not found', async () => {
request.mockReturnValue(Promise.reject({ status: 404 } as FetchError));
const storage = usePluginUserStorage();
await storage.getItem('key');
expect(localStorage.getItem).toHaveBeenCalled();
expect(localStorage.getItem).toHaveBeenCalledWith('plugin-id:abc:key');
});
it('returns the value from the user storage', async () => {
@@ -73,8 +73,8 @@ describe('userStorage', () => {
it('use localStorage if the user is not logged in', async () => {
config.bootData.user.isSignedIn = false;
const storage = usePluginUserStorage();
storage.setItem('key', 'value');
expect(localStorage.setItem).toHaveBeenCalled();
await storage.setItem('key', 'value');
expect(localStorage.setItem).toHaveBeenCalledWith('plugin-id:abc:key', 'value');
});
it('creates a new user storage if it does not exist', async () => {
@@ -37,9 +37,9 @@ async function apiRequest<T>(requestOptions: RequestOptions) {
/**
* A class for interacting with the backend user storage.
* Unexported because it is currently only be used through the useUserStorage hook.
* Exposed internally only to avoid misuse (wrong service name)..
*/
class UserStorage {
export class UserStorage {
private service: string;
private resourceName: string;
private userUID: string;
@@ -76,13 +76,13 @@ class UserStorage {
async getItem(key: string): Promise<string | null> {
if (!this.canUseUserStorage) {
// Fallback to localStorage
return localStorage.getItem(this.resourceName);
return localStorage.getItem(`${this.resourceName}:${key}`);
}
// Ensure this.storageSpec is initialized
await this.init();
if (!this.storageSpec) {
// Also, fallback to localStorage for backward compatibility
return localStorage.getItem(this.resourceName);
return localStorage.getItem(`${this.resourceName}:${key}`);
}
return this.storageSpec.data[key];
}
@@ -90,7 +90,7 @@ class UserStorage {
async setItem(key: string, value: string): Promise<void> {
if (!this.canUseUserStorage) {
// Fallback to localStorage
localStorage.setItem(key, value);
localStorage.setItem(`${this.resourceName}:${key}`, value);
return;
}