mirror of
https://gitlab.com/walljm/dynamicbible.git
synced 2025-07-23 23:39:50 -04:00
refactor card-cache operations to new file in common
This commit is contained in:
parent
5934193702
commit
72bcf32915
75
src/src/app/common/card-cache-operations.spec.ts
Normal file
75
src/src/app/common/card-cache-operations.spec.ts
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
import { CardType, CardItem } from '../models/card-state';
|
||||||
|
import { NoteItem } from '../models/note-state';
|
||||||
|
import { HashTable } from './hashtable';
|
||||||
|
import { updateInCardCache, getCardCacheKey, removeFromCardCache } from './card-cache-operations';
|
||||||
|
|
||||||
|
describe('Card Cache', () => {
|
||||||
|
it('updateCache', () => {
|
||||||
|
const card1: CardItem = {
|
||||||
|
qry: 'jason',
|
||||||
|
type: CardType.Passage,
|
||||||
|
data: null,
|
||||||
|
};
|
||||||
|
const card2: CardItem = {
|
||||||
|
qry: 'jason',
|
||||||
|
type: CardType.Passage,
|
||||||
|
data: {
|
||||||
|
id: 'adsf',
|
||||||
|
xref: '',
|
||||||
|
title: 'adsf',
|
||||||
|
content: '',
|
||||||
|
} as NoteItem,
|
||||||
|
};
|
||||||
|
const card3: CardItem = {
|
||||||
|
qry: 'jason3',
|
||||||
|
type: CardType.Passage,
|
||||||
|
data: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
const cache: HashTable<CardItem> = {};
|
||||||
|
let newCache = updateInCardCache(card1, cache);
|
||||||
|
|
||||||
|
expect(newCache[getCardCacheKey(card1)].qry).toBe('jason', 'Should have added the card');
|
||||||
|
expect(newCache[getCardCacheKey(card1)].data).toBe(null, 'Should have null data');
|
||||||
|
|
||||||
|
newCache = updateInCardCache(card2, newCache);
|
||||||
|
expect(newCache[getCardCacheKey(card2)].qry).toBe('jason', 'Should have added the card');
|
||||||
|
expect((newCache[getCardCacheKey(card1)].data as NoteItem).title).toBe('adsf', 'Should have added the card');
|
||||||
|
expect(Object.keys(newCache).length).toBe(1, 'Should still have only 1 item.');
|
||||||
|
|
||||||
|
newCache = updateInCardCache(card3, newCache);
|
||||||
|
expect(newCache[getCardCacheKey(card3)].qry).toBe('jason3', 'Should have added the card');
|
||||||
|
expect(Object.keys(newCache).length).toBe(2, 'Should have 2 items.');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('removeFromCache', () => {
|
||||||
|
const card1: CardItem = {
|
||||||
|
qry: 'jason',
|
||||||
|
type: CardType.Passage,
|
||||||
|
data: null,
|
||||||
|
};
|
||||||
|
const card2: CardItem = {
|
||||||
|
qry: 'jason',
|
||||||
|
type: CardType.Passage,
|
||||||
|
data: {
|
||||||
|
id: 'adsf',
|
||||||
|
xref: '',
|
||||||
|
title: 'adsf',
|
||||||
|
content: '',
|
||||||
|
} as NoteItem,
|
||||||
|
};
|
||||||
|
const card3: CardItem = {
|
||||||
|
qry: 'jason3',
|
||||||
|
type: CardType.Passage,
|
||||||
|
data: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
const cache: HashTable<CardItem> = {};
|
||||||
|
let newCache = updateInCardCache(card1, cache);
|
||||||
|
newCache = updateInCardCache(card3, newCache);
|
||||||
|
expect(Object.keys(newCache).length).toBe(2, 'Should have 2 items.');
|
||||||
|
|
||||||
|
newCache = removeFromCardCache(card1, newCache);
|
||||||
|
expect(Object.keys(newCache).length).toBe(1, 'Should remove 1 item');
|
||||||
|
});
|
||||||
|
});
|
23
src/src/app/common/card-cache-operations.ts
Normal file
23
src/src/app/common/card-cache-operations.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import { HashTable } from '../common/hashtable';
|
||||||
|
import { CardItem, DataReference } from '../models/card-state';
|
||||||
|
|
||||||
|
export function updateInCardCache(card: CardItem, cardCache: HashTable<CardItem>): HashTable<CardItem> {
|
||||||
|
const cache = { ...cardCache };
|
||||||
|
cache[getCardCacheKey(card)] = card;
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function removeFromCardCache(card: CardItem, cardCache: HashTable<CardItem>): HashTable<CardItem> {
|
||||||
|
const cache = { ...cardCache };
|
||||||
|
delete cache[getCardCacheKey(card)];
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getFromCardCache(ref: DataReference, cardCache: HashTable<CardItem>) {
|
||||||
|
const key = getCardCacheKey(ref);
|
||||||
|
return cardCache[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getCardCacheKey(card: DataReference) {
|
||||||
|
return `${card.qry}:${card.type}`;
|
||||||
|
}
|
@ -11,7 +11,7 @@ import { MatSnackBar } from '@angular/material/snack-bar';
|
|||||||
import { PageEditModalComponent } from '../page-edit-modal/page-edit-modal.component';
|
import { PageEditModalComponent } from '../page-edit-modal/page-edit-modal.component';
|
||||||
import { HashTable } from 'src/app/common/hashtable';
|
import { HashTable } from 'src/app/common/hashtable';
|
||||||
import { SubscriberBase } from 'src/app/common/subscriber-base';
|
import { SubscriberBase } from 'src/app/common/subscriber-base';
|
||||||
import { getCardFromCache } from 'src/app/services/app-state-reducer';
|
import { getFromCardCache } from 'src/app/common/card-cache-operations';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-saved-page-card',
|
selector: 'app-saved-page-card',
|
||||||
@ -41,7 +41,7 @@ export class SavedPageCardComponent extends SubscriberBase implements OnInit {
|
|||||||
|
|
||||||
format(item: DataReference) {
|
format(item: DataReference) {
|
||||||
if (item.type === CardType.Note) {
|
if (item.type === CardType.Note) {
|
||||||
return `Note: ${(getCardFromCache(item, this.cache).data as NoteItem).title}`;
|
return `Note: ${(getFromCardCache(item, this.cache).data as NoteItem).title}`;
|
||||||
} else if (item.type === CardType.Passage) {
|
} else if (item.type === CardType.Passage) {
|
||||||
return `Passage: ${item.qry}`;
|
return `Passage: ${item.qry}`;
|
||||||
} else if (item.type === CardType.Strongs) {
|
} else if (item.type === CardType.Strongs) {
|
||||||
|
@ -6,10 +6,9 @@ import { MatAutocompleteTrigger, MatAutocomplete } from '@angular/material/autoc
|
|||||||
import { AppService } from '../../services/app.service';
|
import { AppService } from '../../services/app.service';
|
||||||
import { NavService } from '../../services/nav.service';
|
import { NavService } from '../../services/nav.service';
|
||||||
import { SubscriberBase } from '../../common/subscriber-base';
|
import { SubscriberBase } from '../../common/subscriber-base';
|
||||||
import { BibleReference } from '../../common/bible-reference';
|
|
||||||
import { VersePickerModalComponent } from '../../components/verse-picker-modal/verse-picker-modal.component';
|
import { VersePickerModalComponent } from '../../components/verse-picker-modal/verse-picker-modal.component';
|
||||||
import { CardItem, CardType } from 'src/app/models/card-state';
|
import { CardItem, CardType } from 'src/app/models/card-state';
|
||||||
import { getCardFromCache } from 'src/app/services/app-state-reducer';
|
import { getFromCardCache } from 'src/app/common/card-cache-operations';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-search-page',
|
selector: 'app-search-page',
|
||||||
@ -18,7 +17,7 @@ import { getCardFromCache } from 'src/app/services/app-state-reducer';
|
|||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class SearchPage extends SubscriberBase implements OnInit {
|
export class SearchPage extends SubscriberBase implements OnInit {
|
||||||
cards$ = this.appService.select((state) => state.currentCards.map((o) => getCardFromCache(o, state.cardCache)));
|
cards$ = this.appService.select((state) => state.currentCards.map((o) => getFromCardCache(o, state.cardCache)));
|
||||||
suggestions$ = this.appService.select((state) => state.autocomplete);
|
suggestions$ = this.appService.select((state) => state.autocomplete);
|
||||||
|
|
||||||
savedPagedLoaded = false;
|
savedPagedLoaded = false;
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
import { TestBed } from '@angular/core/testing';
|
import { TestBed } from '@angular/core/testing';
|
||||||
import { reducer, getNewestStorable, updateCache, getCardItemKey, removeFromCache } from './app-state-reducer';
|
import { reducer, getNewestStorable } from './app-state-reducer';
|
||||||
import { AppActionFactory } from './app-state-actions';
|
import { AppActionFactory } from './app-state-actions';
|
||||||
import { Overlap } from '../common/bible-reference';
|
import { Overlap } from '../common/bible-reference';
|
||||||
import { Storable } from '../common/storable';
|
import { Storable } from '../common/storable';
|
||||||
import { CardType, CardItem } from '../models/card-state';
|
import { CardType, CardItem } from '../models/card-state';
|
||||||
import { SavedPage } from '../models/page-state';
|
import { SavedPage } from '../models/page-state';
|
||||||
import { AppState } from '../models/app-state';
|
import { AppState } from '../models/app-state';
|
||||||
import { HashTable } from '../common/hashtable';
|
|
||||||
import { NoteItem } from '../models/note-state';
|
|
||||||
|
|
||||||
describe('getNewestStorable', () => {
|
describe('getNewestStorable', () => {
|
||||||
it('maybeMutateStorable', () => {
|
it('maybeMutateStorable', () => {
|
||||||
@ -28,77 +26,6 @@ describe('getNewestStorable', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Card Cache', () => {
|
|
||||||
it('updateCache', () => {
|
|
||||||
const card1: CardItem = {
|
|
||||||
qry: 'jason',
|
|
||||||
type: CardType.Passage,
|
|
||||||
data: null,
|
|
||||||
};
|
|
||||||
const card2: CardItem = {
|
|
||||||
qry: 'jason',
|
|
||||||
type: CardType.Passage,
|
|
||||||
data: {
|
|
||||||
id: 'adsf',
|
|
||||||
xref: '',
|
|
||||||
title: 'adsf',
|
|
||||||
content: '',
|
|
||||||
} as NoteItem,
|
|
||||||
};
|
|
||||||
const card3: CardItem = {
|
|
||||||
qry: 'jason3',
|
|
||||||
type: CardType.Passage,
|
|
||||||
data: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
const cache: HashTable<CardItem> = {};
|
|
||||||
let newCache = updateCache(card1, cache);
|
|
||||||
|
|
||||||
expect(newCache[getCardItemKey(card1)].qry).toBe('jason', 'Should have added the card');
|
|
||||||
expect(newCache[getCardItemKey(card1)].data).toBe(null, 'Should have null data');
|
|
||||||
|
|
||||||
newCache = updateCache(card2, newCache);
|
|
||||||
expect(newCache[getCardItemKey(card2)].qry).toBe('jason', 'Should have added the card');
|
|
||||||
expect((newCache[getCardItemKey(card1)].data as NoteItem).title).toBe('adsf', 'Should have added the card');
|
|
||||||
expect(Object.keys(newCache).length).toBe(1, 'Should still have only 1 item.');
|
|
||||||
|
|
||||||
newCache = updateCache(card3, newCache);
|
|
||||||
expect(newCache[getCardItemKey(card3)].qry).toBe('jason3', 'Should have added the card');
|
|
||||||
expect(Object.keys(newCache).length).toBe(2, 'Should have 2 items.');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('removeFromCache', () => {
|
|
||||||
const card1: CardItem = {
|
|
||||||
qry: 'jason',
|
|
||||||
type: CardType.Passage,
|
|
||||||
data: null,
|
|
||||||
};
|
|
||||||
const card2: CardItem = {
|
|
||||||
qry: 'jason',
|
|
||||||
type: CardType.Passage,
|
|
||||||
data: {
|
|
||||||
id: 'adsf',
|
|
||||||
xref: '',
|
|
||||||
title: 'adsf',
|
|
||||||
content: '',
|
|
||||||
} as NoteItem,
|
|
||||||
};
|
|
||||||
const card3: CardItem = {
|
|
||||||
qry: 'jason3',
|
|
||||||
type: CardType.Passage,
|
|
||||||
data: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
const cache: HashTable<CardItem> = {};
|
|
||||||
let newCache = updateCache(card1, cache);
|
|
||||||
newCache = updateCache(card3, newCache);
|
|
||||||
expect(Object.keys(newCache).length).toBe(2, 'Should have 2 items.');
|
|
||||||
|
|
||||||
newCache = removeFromCache(card1, newCache);
|
|
||||||
expect(Object.keys(newCache).length).toBe(1, 'Should remove 1 item');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('AppService Reducer', () => {
|
describe('AppService Reducer', () => {
|
||||||
const preState = {
|
const preState = {
|
||||||
user: null,
|
user: null,
|
||||||
|
@ -5,13 +5,13 @@ import { IStorable, Storable } from '../common/storable';
|
|||||||
import { NoteItem } from '../models/note-state';
|
import { NoteItem } from '../models/note-state';
|
||||||
|
|
||||||
import { mergeCardList } from '../common/card-operations';
|
import { mergeCardList } from '../common/card-operations';
|
||||||
|
import { updateInCardCache, removeFromCardCache, getFromCardCache } from '../common/card-cache-operations';
|
||||||
|
|
||||||
import { AppAction, AppActionFactory } from './app-state-actions';
|
import { AppAction, AppActionFactory } from './app-state-actions';
|
||||||
import { initialState } from './app-state-initial-state';
|
import { initialState } from './app-state-initial-state';
|
||||||
import { SavedPage } from '../models/page-state';
|
import { SavedPage } from '../models/page-state';
|
||||||
import { CardType, CardItem, DataReference } from '../models/card-state';
|
import { CardType, CardItem, DataReference } from '../models/card-state';
|
||||||
import { moveItem, moveItemUpOrDown } from '../common/array-operations';
|
import { moveItem, moveItemUpOrDown } from '../common/array-operations';
|
||||||
import { HashTable } from '../common/hashtable';
|
|
||||||
|
|
||||||
export function getNewestStorable<T>(candidate: IStorable<T>, incumbant: IStorable<T>): IStorable<T> {
|
export function getNewestStorable<T>(candidate: IStorable<T>, incumbant: IStorable<T>): IStorable<T> {
|
||||||
// if the candidate is null, then return the state.
|
// if the candidate is null, then return the state.
|
||||||
@ -28,27 +28,6 @@ export function getNewestStorable<T>(candidate: IStorable<T>, incumbant: IStorab
|
|||||||
return incumbant;
|
return incumbant;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function updateCache(card: CardItem, cardCache: HashTable<CardItem>): HashTable<CardItem> {
|
|
||||||
const cache = { ...cardCache };
|
|
||||||
cache[getCardItemKey(card)] = card;
|
|
||||||
return cache;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function removeFromCache(card: CardItem, cardCache: HashTable<CardItem>): HashTable<CardItem> {
|
|
||||||
const cache = { ...cardCache };
|
|
||||||
delete cache[getCardItemKey(card)];
|
|
||||||
return cache;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getCardItemKey(card: DataReference) {
|
|
||||||
return `${card.qry}:${card.type}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getCardFromCache(ref: DataReference, cardCache: HashTable<CardItem>) {
|
|
||||||
const key = getCardItemKey(ref);
|
|
||||||
return cardCache[key];
|
|
||||||
}
|
|
||||||
|
|
||||||
export function reducer(state: AppState, action: AppAction): AppState {
|
export function reducer(state: AppState, action: AppAction): AppState {
|
||||||
// somtimes the state is null. lets not complain if that happens.
|
// somtimes the state is null. lets not complain if that happens.
|
||||||
if (state === undefined) {
|
if (state === undefined) {
|
||||||
@ -287,7 +266,7 @@ export function reducer(state: AppState, action: AppAction): AppState {
|
|||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
currentCards: cards,
|
currentCards: cards,
|
||||||
cardCache: updateCache(action.card, state.cardCache),
|
cardCache: updateInCardCache(action.card, state.cardCache),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case 'UPDATE_CARD': {
|
case 'UPDATE_CARD': {
|
||||||
@ -299,7 +278,7 @@ export function reducer(state: AppState, action: AppAction): AppState {
|
|||||||
}
|
}
|
||||||
return c;
|
return c;
|
||||||
}),
|
}),
|
||||||
cardCache: updateCache(action.newCard, removeFromCache(action.oldCard, state.cardCache)),
|
cardCache: updateInCardCache(action.newCard, removeFromCardCache(action.oldCard, state.cardCache)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case 'REMOVE_CARD': {
|
case 'REMOVE_CARD': {
|
||||||
@ -329,7 +308,7 @@ export function reducer(state: AppState, action: AppAction): AppState {
|
|||||||
currentSavedPage,
|
currentSavedPage,
|
||||||
savedPages,
|
savedPages,
|
||||||
currentCards: [...state.currentCards.filter((c) => c !== action.card)],
|
currentCards: [...state.currentCards.filter((c) => c !== action.card)],
|
||||||
cardCache: removeFromCache(action.card, state.cardCache),
|
cardCache: removeFromCardCache(action.card, state.cardCache),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case 'MOVE_CARD': {
|
case 'MOVE_CARD': {
|
||||||
@ -344,7 +323,7 @@ export function reducer(state: AppState, action: AppAction): AppState {
|
|||||||
case 'UPDATE_CARDS': {
|
case 'UPDATE_CARDS': {
|
||||||
let cardCache = { ...state.cardCache };
|
let cardCache = { ...state.cardCache };
|
||||||
for (const card of action.cards) {
|
for (const card of action.cards) {
|
||||||
cardCache = updateCache(card, cardCache);
|
cardCache = updateInCardCache(card, cardCache);
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
@ -431,7 +410,7 @@ export function reducer(state: AppState, action: AppAction): AppState {
|
|||||||
|
|
||||||
const cards = [
|
const cards = [
|
||||||
...state.currentCards.map((o) => {
|
...state.currentCards.map((o) => {
|
||||||
const n = getCardFromCache(o, state.cardCache).data as NoteItem;
|
const n = getFromCardCache(o, state.cardCache).data as NoteItem;
|
||||||
if (n && n.id === action.note.id) {
|
if (n && n.id === action.note.id) {
|
||||||
return {
|
return {
|
||||||
...o,
|
...o,
|
||||||
@ -452,7 +431,7 @@ export function reducer(state: AppState, action: AppAction): AppState {
|
|||||||
return {
|
return {
|
||||||
...sp,
|
...sp,
|
||||||
queries: sp.queries.map((o) => {
|
queries: sp.queries.map((o) => {
|
||||||
const n = getCardFromCache(o, state.cardCache).data as NoteItem;
|
const n = getFromCardCache(o, state.cardCache).data as NoteItem;
|
||||||
if (n && n.id === action.note.id) {
|
if (n && n.id === action.note.id) {
|
||||||
return {
|
return {
|
||||||
...o,
|
...o,
|
||||||
@ -482,7 +461,7 @@ export function reducer(state: AppState, action: AppAction): AppState {
|
|||||||
|
|
||||||
const cards = [
|
const cards = [
|
||||||
...state.currentCards.filter((o) => {
|
...state.currentCards.filter((o) => {
|
||||||
const n = getCardFromCache(o, state.cardCache).data as NoteItem;
|
const n = getFromCardCache(o, state.cardCache).data as NoteItem;
|
||||||
return !n || n.id !== action.note.id;
|
return !n || n.id !== action.note.id;
|
||||||
}),
|
}),
|
||||||
];
|
];
|
||||||
@ -494,7 +473,7 @@ export function reducer(state: AppState, action: AppAction): AppState {
|
|||||||
return {
|
return {
|
||||||
...sp,
|
...sp,
|
||||||
queries: sp.queries.filter((o) => {
|
queries: sp.queries.filter((o) => {
|
||||||
const n = getCardFromCache(o, state.cardCache).data as NoteItem;
|
const n = getFromCardCache(o, state.cardCache).data as NoteItem;
|
||||||
return !n || n.id !== action.note.id;
|
return !n || n.id !== action.note.id;
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
@ -183,6 +183,7 @@ export class AppService extends createStateService(reducer, initialState) {
|
|||||||
updateSettings(settings: IStorable<Settings>) {
|
updateSettings(settings: IStorable<Settings>) {
|
||||||
this.dispatch(AppActionFactory.newUpdateSettings(settings));
|
this.dispatch(AppActionFactory.newUpdateSettings(settings));
|
||||||
}
|
}
|
||||||
|
|
||||||
updateDisplaySettings(displaySettings: DisplaySettings) {
|
updateDisplaySettings(displaySettings: DisplaySettings) {
|
||||||
const state = this.getState();
|
const state = this.getState();
|
||||||
|
|
||||||
@ -195,6 +196,7 @@ export class AppService extends createStateService(reducer, initialState) {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
updatePageSettings(pageSettings: PageSettings) {
|
updatePageSettings(pageSettings: PageSettings) {
|
||||||
const state = this.getState();
|
const state = this.getState();
|
||||||
|
|
||||||
@ -207,6 +209,7 @@ export class AppService extends createStateService(reducer, initialState) {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
//#region Notes
|
//#region Notes
|
||||||
|
Loading…
x
Reference in New Issue
Block a user