mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-05-12 17:04:57 +00:00
AAE-32763 Custom column visibility is not persistent after refresh (#10728)
* [AAE-32763] fixed retrieving preferences from local storage * [AAE-32763] added a test * [AAE-32763] Reverted to old implementation * [AAE-32763] renamed test * [AAE-32763] Be able to use getitems from local storage in the same way as cloud storage * [AAE-32763] added more tests
This commit is contained in:
parent
3475098f32
commit
6703b8b7da
@ -26,42 +26,57 @@ describe('StorageService', () => {
|
|||||||
const key = 'test_key';
|
const key = 'test_key';
|
||||||
const value = 'test_value';
|
const value = 'test_value';
|
||||||
|
|
||||||
describe('with prefix', () => {
|
describe('with local storage and prefix', () => {
|
||||||
beforeEach(() => {
|
beforeEach(async () => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [NoopTranslateModule, NoopAuthModule]
|
imports: [NoopTranslateModule, NoopAuthModule]
|
||||||
});
|
});
|
||||||
appConfig = TestBed.inject(AppConfigService);
|
appConfig = TestBed.inject(AppConfigService);
|
||||||
storage = TestBed.inject(StorageService);
|
storage = TestBed.inject(StorageService);
|
||||||
|
await appConfig.load();
|
||||||
|
storage.clear();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should get the prefix for the storage from app config', async () => {
|
it('should get the prefix for the storage from app config', () => {
|
||||||
await appConfig.load();
|
|
||||||
expect(storage.prefix).toBe('ADF_APP_');
|
expect(storage.prefix).toBe('ADF_APP_');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set a property with the prefix in the local storage', async () => {
|
it('should set a property with the prefix in the local storage', () => {
|
||||||
await appConfig.load();
|
|
||||||
|
|
||||||
storage.clear();
|
|
||||||
storage.setItem(key, value);
|
storage.setItem(key, value);
|
||||||
const storageKey = localStorage.key(0);
|
const storageKey = localStorage.key(0);
|
||||||
expect(storageKey).toBe('ADF_APP_' + key);
|
expect(storageKey).toBe('ADF_APP_' + key);
|
||||||
expect(localStorage.getItem(storageKey)).toBe(value);
|
expect(localStorage.getItem(storageKey)).toBe(value);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be able to get a property from the local storage', async () => {
|
it('should be able to get a property from the local storage', () => {
|
||||||
storage.clear();
|
|
||||||
|
|
||||||
await appConfig.load();
|
|
||||||
storage.setItem(key, value);
|
storage.setItem(key, value);
|
||||||
|
|
||||||
expect(storage.getItem(key)).toBe(value);
|
expect(storage.getItem(key)).toBe(value);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should retrieve all items with the prefix from local storage', () => {
|
||||||
|
localStorage.setItem('ADF_APP_key1', 'value1');
|
||||||
|
localStorage.setItem('ADF_APP_key2', 'value2');
|
||||||
|
|
||||||
|
const items = storage.getItems();
|
||||||
|
|
||||||
|
expect(items).toEqual({
|
||||||
|
key1: 'value1',
|
||||||
|
key2: 'value2'
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('without prefix', () => {
|
it('should return an empty object if no items match the prefix in local storage', () => {
|
||||||
beforeEach(() => {
|
localStorage.setItem('other_key', 'value');
|
||||||
|
|
||||||
|
const items = storage.getItems();
|
||||||
|
|
||||||
|
expect(items).toEqual({});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('without local storage and prefix', () => {
|
||||||
|
beforeEach(async () => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [NoopAuthModule]
|
imports: [NoopAuthModule]
|
||||||
});
|
});
|
||||||
@ -73,18 +88,64 @@ describe('StorageService', () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
storage = TestBed.inject(StorageService);
|
storage = TestBed.inject(StorageService);
|
||||||
|
await appConfig.load();
|
||||||
|
storage.clear();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set an empty prefix when the it is not defined in the app config', async () => {
|
it('should set an empty prefix when the it is not defined in the app config', () => {
|
||||||
await appConfig.load();
|
|
||||||
expect(storage.prefix).toBe('');
|
expect(storage.prefix).toBe('');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set a property without a prefix in the local storage', async () => {
|
it('should set a property without a prefix in the local storage', () => {
|
||||||
await appConfig.load();
|
|
||||||
storage.setItem(key, value);
|
storage.setItem(key, value);
|
||||||
|
|
||||||
expect(localStorage.getItem(key)).toBe(value);
|
expect(localStorage.getItem(key)).toBe(value);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should retrieve all items without a prefix from local storage', () => {
|
||||||
|
localStorage.setItem('key1', 'value1');
|
||||||
|
localStorage.setItem('key2', 'value2');
|
||||||
|
|
||||||
|
const items = storage.getItems();
|
||||||
|
expect(items).toEqual({
|
||||||
|
key1: 'value1',
|
||||||
|
key2: 'value2'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('with memory storage', () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
Object.defineProperty(window, 'localStorage', {
|
||||||
|
value: undefined,
|
||||||
|
configurable: true
|
||||||
|
});
|
||||||
|
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [NoopTranslateModule, NoopAuthModule]
|
||||||
|
});
|
||||||
|
appConfig = TestBed.inject(AppConfigService);
|
||||||
|
storage = TestBed.inject(StorageService);
|
||||||
|
await appConfig.load();
|
||||||
|
storage.clear();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to get a property from storage', () => {
|
||||||
|
storage.setItem(key, value);
|
||||||
|
|
||||||
|
expect(storage.getItem(key)).toBe(value);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should retrieve all items from storage', () => {
|
||||||
|
storage.setItem('key1', 'value1');
|
||||||
|
storage.setItem('key2', 'value2');
|
||||||
|
|
||||||
|
const items = storage.getItems();
|
||||||
|
|
||||||
|
expect(items).toEqual({
|
||||||
|
key1: 'value1',
|
||||||
|
key2: 'value2'
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -51,6 +51,33 @@ export class StorageService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all items from the storage.
|
||||||
|
*
|
||||||
|
* @returns All items stored
|
||||||
|
*/
|
||||||
|
getItems(): { [key: string]: any } {
|
||||||
|
const items: { [key: string]: any } = {};
|
||||||
|
if (this.useLocalStorage) {
|
||||||
|
for (let i = 0; i < localStorage.length; i++) {
|
||||||
|
const key = localStorage.key(i);
|
||||||
|
if (key?.startsWith(this.prefix)) {
|
||||||
|
const keyWithoutPrefix = key.slice(this.prefix.length);
|
||||||
|
items[keyWithoutPrefix] = localStorage.getItem(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Object.keys(this.memoryStore).forEach((key) => {
|
||||||
|
if (key.startsWith(this.prefix)) {
|
||||||
|
const unprefixedKey = key.slice(this.prefix.length);
|
||||||
|
items[unprefixedKey] = this.memoryStore[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores an item
|
* Stores an item
|
||||||
*
|
*
|
||||||
|
@ -33,7 +33,7 @@ import {
|
|||||||
} from '@alfresco/adf-core';
|
} from '@alfresco/adf-core';
|
||||||
import { ProcessListCloudService } from '../services/process-list-cloud.service';
|
import { ProcessListCloudService } from '../services/process-list-cloud.service';
|
||||||
import { ProcessListCloudComponent } from './process-list-cloud.component';
|
import { ProcessListCloudComponent } from './process-list-cloud.component';
|
||||||
import { of } from 'rxjs';
|
import { of, throwError } from 'rxjs';
|
||||||
import { shareReplay, skip } from 'rxjs/operators';
|
import { shareReplay, skip } from 'rxjs/operators';
|
||||||
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
|
import { ProcessServiceCloudTestingModule } from '../../../testing/process-service-cloud.testing.module';
|
||||||
import { ProcessListCloudSortingModel } from '../models/process-list-sorting.model';
|
import { ProcessListCloudSortingModel } from '../models/process-list-sorting.model';
|
||||||
@ -272,6 +272,67 @@ describe('ProcessListCloudComponent', () => {
|
|||||||
configureTestingModule('GET');
|
configureTestingModule('GET');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should load preferences', () => {
|
||||||
|
const columnsOrder = ['startDate', 'id'];
|
||||||
|
const columnsVisibility = { startDate: true, id: false };
|
||||||
|
const columnsWidths = { startDate: 100, id: 200 };
|
||||||
|
|
||||||
|
spyOn(preferencesService, 'getPreferences').and.returnValue(
|
||||||
|
of({
|
||||||
|
list: {
|
||||||
|
entries: [
|
||||||
|
{
|
||||||
|
entry: {
|
||||||
|
key: ProcessListCloudPreferences.columnOrder,
|
||||||
|
value: JSON.stringify(columnsOrder)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
entry: {
|
||||||
|
key: ProcessListCloudPreferences.columnsWidths,
|
||||||
|
value: JSON.stringify(columnsWidths)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
entry: {
|
||||||
|
key: ProcessListCloudPreferences.columnsVisibility,
|
||||||
|
value: JSON.stringify(columnsVisibility)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const firstColumn = component.columns[0];
|
||||||
|
expect(firstColumn.id).toBe('startDate');
|
||||||
|
expect(firstColumn.isHidden).toBe(false);
|
||||||
|
expect(firstColumn.width).toBe(100);
|
||||||
|
|
||||||
|
const secondColumn = component.columns[1];
|
||||||
|
expect(secondColumn.id).toBe('id');
|
||||||
|
expect(secondColumn.isHidden).toBe(true);
|
||||||
|
expect(secondColumn.width).toBe(200);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should load table when loading preferences throws an error', () => {
|
||||||
|
spyOn(preferencesService, 'getPreferences').and.returnValue(throwError(() => ({ status: 404 })));
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
const firstColumn = component.columns[0];
|
||||||
|
expect(firstColumn.id).toBe('id');
|
||||||
|
expect(firstColumn.isHidden).toBe(false);
|
||||||
|
expect(firstColumn.width).toBe(undefined);
|
||||||
|
|
||||||
|
const secondColumn = component.columns[1];
|
||||||
|
expect(secondColumn.id).toBe('startDate');
|
||||||
|
expect(secondColumn.isHidden).toBe(false);
|
||||||
|
expect(secondColumn.width).toBe(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
it('should load spinner and show the content', async () => {
|
it('should load spinner and show the content', async () => {
|
||||||
spyOn(processListCloudService, 'getProcessByRequest').and.returnValue(of(fakeProcessCloudList));
|
spyOn(processListCloudService, 'getProcessByRequest').and.returnValue(of(fakeProcessCloudList));
|
||||||
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
|
const appName = new SimpleChange(null, 'FAKE-APP-NAME', true);
|
||||||
|
@ -49,11 +49,11 @@ import {
|
|||||||
UserPreferenceValues
|
UserPreferenceValues
|
||||||
} from '@alfresco/adf-core';
|
} from '@alfresco/adf-core';
|
||||||
import { ProcessListCloudService } from '../services/process-list-cloud.service';
|
import { ProcessListCloudService } from '../services/process-list-cloud.service';
|
||||||
import { BehaviorSubject, combineLatest, Subject } from 'rxjs';
|
import { BehaviorSubject, combineLatest, of, Subject, throwError } from 'rxjs';
|
||||||
import { processCloudPresetsDefaultModel } from '../models/process-cloud-preset.model';
|
import { processCloudPresetsDefaultModel } from '../models/process-cloud-preset.model';
|
||||||
import { ProcessListRequestModel, ProcessQueryCloudRequestModel } from '../models/process-cloud-query-request.model';
|
import { ProcessListRequestModel, ProcessQueryCloudRequestModel } from '../models/process-cloud-query-request.model';
|
||||||
import { ProcessListCloudSortingModel, ProcessListRequestSortingModel } from '../models/process-list-sorting.model';
|
import { ProcessListCloudSortingModel, ProcessListRequestSortingModel } from '../models/process-list-sorting.model';
|
||||||
import { filter, map, switchMap, take, tap } from 'rxjs/operators';
|
import { catchError, filter, map, switchMap, take, tap } from 'rxjs/operators';
|
||||||
import { PreferenceCloudServiceInterface } from '../../../services/preference-cloud.interface';
|
import { PreferenceCloudServiceInterface } from '../../../services/preference-cloud.interface';
|
||||||
import { PROCESS_LISTS_PREFERENCES_SERVICE_TOKEN } from '../../../services/cloud-token.service';
|
import { PROCESS_LISTS_PREFERENCES_SERVICE_TOKEN } from '../../../services/cloud-token.service';
|
||||||
import { ProcessListCloudPreferences } from '../models/process-cloud-preferences';
|
import { ProcessListCloudPreferences } from '../models/process-cloud-preferences';
|
||||||
@ -407,6 +407,17 @@ export class ProcessListCloudComponent
|
|||||||
columnsVisibility: columnsVisibility ? JSON.parse(columnsVisibility.entry.value) : this.columnsVisibility,
|
columnsVisibility: columnsVisibility ? JSON.parse(columnsVisibility.entry.value) : this.columnsVisibility,
|
||||||
columnsWidths: columnsWidths ? JSON.parse(columnsWidths.entry.value) : undefined
|
columnsWidths: columnsWidths ? JSON.parse(columnsWidths.entry.value) : undefined
|
||||||
};
|
};
|
||||||
|
}),
|
||||||
|
catchError((error) => {
|
||||||
|
if (error.status === 404) {
|
||||||
|
return of({
|
||||||
|
columnsOrder: undefined,
|
||||||
|
columnsVisibility: this.columnsVisibility,
|
||||||
|
columnsWidths: undefined
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return throwError(error);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.subscribe(({ columnsOrder, columnsVisibility, columnsWidths }) => {
|
.subscribe(({ columnsOrder, columnsVisibility, columnsWidths }) => {
|
||||||
|
@ -0,0 +1,65 @@
|
|||||||
|
/*!
|
||||||
|
* @license
|
||||||
|
* Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { TestBed } from '@angular/core/testing';
|
||||||
|
import { LocalPreferenceCloudService } from './local-preference-cloud.service';
|
||||||
|
import { StorageService } from '@alfresco/adf-core';
|
||||||
|
|
||||||
|
describe('LocalPreferenceCloudService', () => {
|
||||||
|
let service: LocalPreferenceCloudService;
|
||||||
|
let storageServiceSpy: jasmine.SpyObj<StorageService>;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
const spy = jasmine.createSpyObj('StorageService', ['getItem', 'getItems', 'setItem']);
|
||||||
|
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
providers: [LocalPreferenceCloudService, { provide: StorageService, useValue: spy }]
|
||||||
|
});
|
||||||
|
|
||||||
|
service = TestBed.inject(LocalPreferenceCloudService);
|
||||||
|
storageServiceSpy = TestBed.inject(StorageService) as jasmine.SpyObj<StorageService>;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return preferences for a given key', (done) => {
|
||||||
|
const key = 'testKey';
|
||||||
|
const value = '[{"name": "test"}]';
|
||||||
|
storageServiceSpy.getItem.and.returnValue(value);
|
||||||
|
|
||||||
|
service.getPreferences('', key).subscribe((result) => {
|
||||||
|
expect(result.list.entries[0].entry.key).toBe(key);
|
||||||
|
expect(result.list.entries[0].entry.value).toBe(value);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return all preferences if no key is provided', (done) => {
|
||||||
|
const items = {
|
||||||
|
key1: '[{"name": "test1"}]',
|
||||||
|
key2: '[{"name": "test2"}]'
|
||||||
|
};
|
||||||
|
storageServiceSpy.getItems.and.returnValue(items);
|
||||||
|
|
||||||
|
service.getPreferences('', undefined).subscribe((result) => {
|
||||||
|
expect(result.list.entries.length).toBe(2);
|
||||||
|
expect(result.list.entries[0].entry.key).toBe('key1');
|
||||||
|
expect(result.list.entries[0].entry.value).toBe(items['key1']);
|
||||||
|
expect(result.list.entries[1].entry.key).toBe('key2');
|
||||||
|
expect(result.list.entries[1].entry.value).toBe(items['key2']);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -35,9 +35,18 @@ export class LocalPreferenceCloudService implements PreferenceCloudServiceInterf
|
|||||||
if (key || key === '') {
|
if (key || key === '') {
|
||||||
return of(this.prepareLocalPreferenceResponse(key));
|
return of(this.prepareLocalPreferenceResponse(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const items = this.storage.getItems();
|
||||||
|
const entries = Object.keys(items).map((k) => ({
|
||||||
|
entry: {
|
||||||
|
key: k,
|
||||||
|
value: items[k] || '[]'
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
return of({
|
return of({
|
||||||
list: {
|
list: {
|
||||||
entries: []
|
entries
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user