Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,15 @@ export function UPDATE_ASSESSMENTITEM(state, assessmentItem) {
}

export function UPDATE_ASSESSMENTITEM_FROM_INDEXEDDB(state, { id, ...mods }) {
if (id && state.assessmentItemsMap[id]) {
applyMods(state.assessmentItemsMap[id], mods);
const [contentnode, assessment_id] = id || [null, null];
if (
id &&
state.assessmentItemsMap[contentnode] &&
state.assessmentItemsMap[contentnode][assessment_id]
) {
Vue.set(state.assessmentItemsMap[contentnode], assessment_id, {
...applyMods(state.assessmentItemsMap[contentnode][assessment_id], mods),
});
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import Vue from 'vue';
import { SAVE_NEXT_STEPS, REMOVE_PREVIOUS_STEP, ADD_PREVIOUS_STEP } from '../mutations';
import { factory } from '../../../store';

describe('contentNode mutations', () => {
describe('SAVE_NEXT_STEPS', () => {
Expand Down Expand Up @@ -186,4 +188,56 @@ describe('contentNode mutations', () => {
expect(state.previousStepsMap).toEqual(maps.previousStepsMap);
});
});
describe('UPDATE_CONTENTNODE_FROM_INDEXEDDB', () => {
it('should ensure that nested object properties are reactively set', async () => {
const store = factory();
store.commit('contentNode/ADD_CONTENTNODE', { id: 'test', extra_fields: null });
await Vue.nextTick();
const spy = jest.fn();
store.watch(state => {
const node = state.contentNode.contentNodesMap.test;
const value =
node &&
node.extra_fields &&
node.extra_fields.options &&
node.extra_fields.options.completion_criteria &&
node.extra_fields.options.completion_criteria.threshold;
spy(value);
});
store.commit('contentNode/UPDATE_CONTENTNODE_FROM_INDEXEDDB', {
id: 'test',
'extra_fields.options.modality': 'QUIZ',
});
await Vue.nextTick();
expect(store.state.contentNode.contentNodesMap.test.extra_fields.options.modality).toEqual(
'QUIZ'
);
store.commit('contentNode/UPDATE_CONTENTNODE_FROM_INDEXEDDB', {
id: 'test',
'extra_fields.options.modality': null,
'extra_fields.options.completion_criteria.model': 'time',
});
await Vue.nextTick();
expect(
store.state.contentNode.contentNodesMap.test.extra_fields.options.modality
).toBeUndefined();
expect(
store.state.contentNode.contentNodesMap.test.extra_fields.options.completion_criteria.model
).toEqual('time');
store.commit('contentNode/UPDATE_CONTENTNODE_FROM_INDEXEDDB', {
id: 'test',
'extra_fields.options.completion_criteria.threshold': 5,
});
await Vue.nextTick();
expect(
store.state.contentNode.contentNodesMap.test.extra_fields.options.completion_criteria.model
).toEqual('time');
expect(
store.state.contentNode.contentNodesMap.test.extra_fields.options.completion_criteria
.threshold
).toEqual(5);
// The watch function is invoked when initially set, so this is invoked 4 times, not 3.
expect(spy).toHaveBeenCalledTimes(4);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ export function ADD_CONTENTNODES(state, contentNodes = []) {

export function UPDATE_CONTENTNODE_FROM_INDEXEDDB(state, { id, ...updates }) {
if (id && state.contentNodesMap[id]) {
applyMods(state.contentNodesMap[id], updates);
// Need to do object spread to return a new object for setting in the map
// otherwise nested changes will not trigger reactive updates
Vue.set(state.contentNodesMap, id, { ...applyMods(state.contentNodesMap[id], updates) });
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export function UPDATE_SAVEDSEARCH(state, search) {

export function UPDATE_SAVEDSEARCH_FROM_INDEXEDDB(state, { id, ...updates }) {
if (id && state.savedSearches[id]) {
applyMods(state.savedSearches[id], updates);
Vue.set(state.savedSearches, id, { ...applyMods(state.savedSearches[id], updates) });
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export default {
},
UPDATE_ASYNC_TASK_FROM_INDEXEDDB(state, { task_id, ...mods }) {
if (task_id && state.asyncTasksMap[task_id]) {
applyMods(state.asyncTasksMap[task_id], mods);
Vue.set(state.asyncTasksMap, task_id, { ...applyMods(state.asyncTasksMap[task_id], mods) });
}
},
REMOVE_ASYNC_TASK(state, asyncTask) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export function UPDATE_CHANNELSET(state, { id, ...payload }) {

export function UPDATE_CHANNELSET_FROM_INDEXEDDB(state, { id, ...mods }) {
if (id && state.channelSetsMap[id]) {
applyMods(state.channelSetsMap[id], mods);
Vue.set(state.channelSetsMap, id, { ...applyMods(state.channelSetsMap[id], mods) });
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,12 @@ import Dexie from 'dexie';
import flatMap from 'lodash/flatMap';
import { CHANGE_TYPES } from './constants';
import { INDEXEDDB_RESOURCES } from './registry';

function applyModifications(obj, modifications) {
Object.keys(modifications).forEach(function(keyPath) {
Dexie.setByKeyPath(obj, keyPath, modifications[keyPath]);
});
return obj;
}
import { applyMods } from './applyRemoteChanges';

function combineCreateAndUpdate(oldChange, newChange) {
// Apply modifications to existing object.
// Passed in object should be modifiable, so no need to clone.
applyModifications(oldChange.obj, newChange.mods);
applyMods(oldChange.obj, newChange.mods);
return oldChange;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1791,6 +1791,10 @@ export const Task = new IndexedDBResource({
tableName: TABLE_NAMES.TASK,
idField: 'task_id',
setTasks(tasks) {
for (let task of tasks) {
// Coerce channel_id to be a simple hex string
task.channel_id = task.channel_id.replace('-', '');
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could probably remove the - replacement here with this change

}
return this.transaction({ mode: 'rw', source: IGNORED_SOURCE }, () => {
return this.table
.where(this.idField)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,10 @@ export function UPDATE_CHANNEL(state, { id, content_defaults = {}, ...payload }
});
}
}

export function UPDATE_CHANNEL_FROM_INDEXEDDB(state, { id, ...mods }) {
if (id && state.channelsMap[id]) {
applyMods(state.channelsMap[id], mods);
Vue.set(state.channelsMap, id, { ...applyMods(state.channelsMap[id], mods) });
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,15 @@ import { applyMods } from 'shared/data/applyRemoteChanges';

function updateFileMaps(state, file) {
if (file.assessment_item) {
Vue.set(
state.assessmentItemFilesMap,
file.assessment_item,
mergeMapItem(state.assessmentItemFilesMap[file.assessment_item] || {}, file)
);
if (!state.assessmentItemFilesMap[file.assessment_item]) {
Vue.set(state.assessmentItemFilesMap, file.assessment_item, {});
}
Vue.set(state.assessmentItemFilesMap[file.assessment_item], file.id, file);
} else if (file.contentnode) {
Vue.set(
state.contentNodeFilesMap,
file.contentnode,
mergeMapItem(state.contentNodeFilesMap[file.contentnode] || {}, file)
);
if (!state.contentNodeFilesMap[file.contentnode]) {
Vue.set(state.contentNodeFilesMap, file.contentnode, {});
}
Vue.set(state.contentNodeFilesMap[file.contentnode], file.id, file);
}
}

Expand All @@ -36,7 +34,7 @@ export function ADD_FILES(state, files = []) {

export function UPDATE_FILE_FROM_INDEXEDDB(state, { id, ...mods }) {
if (id && state.fileUploadsMap[id]) {
applyMods(state.fileUploadsMap[id], mods);
Vue.set(state.fileUploadsMap, id, { ...applyMods(state.fileUploadsMap[id], mods) });
updateFileMaps(state, state.fileUploadsMap[id]);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export default {
},
UPDATE_SESSION_FROM_INDEXEDDB(state, { id, ...mods }) {
if (id === state.currentUser.id) {
applyMods(state.currentUser, mods);
state.currentUser = { ...applyMods(state.currentUser, mods) };
}
},
REMOVE_SESSION(state) {
Expand Down