Forked from
Stud.IP / Stud.IP
623 commits behind the upstream repository.
-
Ron Lucke authored
Closes #4477 Merge request studip/studip!3263
Ron Lucke authoredCloses #4477 Merge request studip/studip!3263
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
courseware.module.js 54.47 KiB
import axios from 'axios';
const getDefaultState = () => {
return {
blockAdder: {},
containerAdder: false,
consumeMode: false,
context: {},
courseware: {},
currentElement: {},
licenses: null, // we need a route for License SORM
httpClient: null,
lastElement: null,
msg: 'Dehydrated',
msgCompanionOverlay: '',
styleCompanionOverlay: 'default',
pluginManager: null,
showCompanionOverlay: false,
showToolbar: false,
selectedToolbarItem: 'contents',
urlHelper: null,
userId: null,
viewMode: 'read',
dashboardViewMode: 'default',
userIsTeacherInCourse: false,
showStructuralElementEditDialog: false,
showStructuralElementAddDialog: false,
showStructuralElementAddChooserDialog: false,
showStructuralElementImportDialog: false,
showStructuralElementCopyDialog: false,
showStructuralElementLinkDialog: false,
showStructuralElementExportDialog: false,
showStructuralElementExportChooserDialog: false,
showStructuralElementPdfExportDialog: false,
showStructuralElementInfoDialog: false,
showStructuralElementDeleteDialog: false,
showStructuralElementOerDialog: false,
showStructuralElementPublicLinkDialog: false,
showStructuralElementRemoveLockDialog: false,
showStructuralElementFeedbackDialog: false,
showStructuralElementFeedbackCreateDialog: false,
showSuggestOerDialog: false,
importFilesState: '',
importFilesProgress: 0,
importStructuresState: '',
importStructuresProgress: 0,
importErrors: [],
exportState: '',
exportProgress: 0,
permissionFilter: 'read',
purposeFilter: 'all',
sourceFilter: 'all',
showOverviewElementAddDialog: false,
bookmarkFilter: 'all',
showSearchResults: false,
searchResults: [],
assistiveLiveContents: '',
progresses: null,
toolbarActive: true,
hideEditLayout: false,
feedbackSettings: null,
processing: false,
};
};
const initialState = getDefaultState();
const getters = {
msg(state) {
return state.msg;
},
currentUser(state, getters, rootState, rootGetters) {
const id = getters.userId;
return rootGetters['users/byId']({ id });
},
lastElement(state) {
return state.lastElement;
},
courseware(state) {
return state.courseware;
},
rootLayout(state, getters) {
return getters.courseware.attributes['root-layout'];
},
showRootElement(state, getters) {
return getters.rootLayout !== 'none';
},
rootId(state, getters) {
return getters.courseware?.relationships?.root?.data?.id;
},
currentElement(state) {
return state.currentElement;
},
currentStructuralElement(state, getters, rootState, rootGetters) {
const id = getters.currentElement;
return rootGetters['courseware-structural-elements/byId']({ id });
},
currentUnit(state, getters, rootState, rootGetters) {
const id = getters.currentStructuralElement.relationships?.unit?.data?.id;
if (id) {
return rootGetters['courseware-units/byId']({ id });
}
return null;
},
currentElementBlocked(state, getters, rootState, rootGetters) {
const elemData = getters.currentStructuralElement?.relationships?.['edit-blocker']?.data;
return elemData !== null && elemData !== '' && getters.currentStructuralElement;
},
currentElementBlockerId(state, getters) {
return getters.currentElementBlocked ? getters.currentStructuralElement?.relationships?.['edit-blocker']?.data?.id : null;
},
currentElementBlockedByThisUser(state, getters) {
return getters.currentElementBlocked && getters.userId === getters.currentElementBlockerId;
},
currentElementBlockedByAnotherUser(state, getters) {
return getters.currentElementBlocked && getters.userId !== getters.currentElementBlockerId;
},
currentElementisLink(state, getters, rootState, rootGetters) {
return getters.currentStructuralElement?.attributes?.['is-link'] === 1;
},
currentStructuralElementImageURL(state, getters) {
return getters.currentStructuralElement?.relationships?.image?.meta?.['download-url'];
},
licenses(state) {
return state.licenses;
},
context(state) {
return state.context;
},
blockTypes(state) {
return state.courseware?.attributes?.['block-types'] ?? [];
},
containerTypes(state) {
return state.courseware?.attributes?.['container-types'] ?? [];
},
favoriteBlockTypes(state) {
const allBlockTypes = state.courseware?.attributes?.['block-types'] ?? [];
const favorites = state.courseware?.attributes?.['favorite-block-types'] ?? [];
return allBlockTypes.filter(({ type }) => favorites.includes(type));
},
viewMode(state) {
return state.viewMode;
},
dashboardViewMode(state) {
return state.dashboardViewMode;
},
showToolbar(state) {
return state.showToolbar;
},
selectedToolbarItem(state) {
return state.selectedToolbarItem;
},
blockAdder(state) {
return state.blockAdder;
},
containerAdder(state) {
return state.containerAdder;
},
showCompanionOverlay(state) {
return state.showCompanionOverlay;
},
msgCompanionOverlay(state) {
return state.msgCompanionOverlay;
},
styleCompanionOverlay(state) {
return state.styleCompanionOverlay;
},
consumeMode(state) {
return state.consumeMode;
},
httpClient(state) {
return state.httpClient;
},
urlHelper(state) {
return state.urlHelper;
},
userId(state) {
return state.userId;
},
userIsTeacherInCourse(state) {
return state.userIsTeacherInCourse;
},
userIsTeacher(state, getters) {
if (getters.courseware.attributes === undefined) {
return getters.userIsTeacherInCourse;
}
return getters.courseware.attributes['is-teacher'];
},
pluginManager(state) {
return state.pluginManager;
},
showStructuralElementEditDialog(state) {
return state.showStructuralElementEditDialog;
},
showStructuralElementAddDialog(state) {
return state.showStructuralElementAddDialog;
},
showStructuralElementAddChooserDialog(state) {
return state.showStructuralElementAddChooserDialog;
},
showStructuralElementCopyDialog(state) {
return state.showStructuralElementCopyDialog;
},
showStructuralElementLinkDialog(state) {
return state.showStructuralElementLinkDialog;
},
showStructuralElementImportDialog(state) {
return state.showStructuralElementImportDialog;
},
showStructuralElementExportDialog(state) {
return state.showStructuralElementExportDialog;
},
showStructuralElementExportChooserDialog(state) {
return state.showStructuralElementExportChooserDialog;
},
showStructuralElementPdfExportDialog(state) {
return state.showStructuralElementPdfExportDialog;
},
showStructuralElementInfoDialog(state) {
return state.showStructuralElementInfoDialog;
},
showStructuralElementOerDialog(state) {
return state.showStructuralElementOerDialog;
},
showStructuralElementDeleteDialog(state) {
return state.showStructuralElementDeleteDialog;
},
showStructuralElementPublicLinkDialog(state) {
return state.showStructuralElementPublicLinkDialog;
},
showStructuralElementRemoveLockDialog(state) {
return state.showStructuralElementRemoveLockDialog;
},
showStructuralElementFeedbackDialog(state) {
return state.showStructuralElementFeedbackDialog;
},
showStructuralElementFeedbackCreateDialog(state) {
return state.showStructuralElementFeedbackCreateDialog;
},
showOverviewElementAddDialog(state) {
return state.showOverviewElementAddDialog;
},
showSuggestOerDialog(state) {
return state.showSuggestOerDialog;
},
importFilesState(state) {
return state.importFilesState;
},
importFilesProgress(state) {
return state.importFilesProgress;
},
importStructuresState(state) {
return state.importStructuresState;
},
importStructuresProgress(state) {
return state.importStructuresProgress;
},
importErrors(state) {
return state.importErrors;
},
exportState(state) {
return state.exportState;
},
exportProgress(state) {
return state.exportProgress;
},
permissionFilter(state) {
return state.permissionFilter;
},
purposeFilter(state) {
return state.purposeFilter;
},
sourceFilter(state) {
return state.sourceFilter;
},
bookmarkFilter(state) {
return state.bookmarkFilter;
},
showSearchResults(state) {
return state.showSearchResults;
},
searchResults(state) {
return state.searchResults;
},
assistiveLiveContents(state) {
return state.assistiveLiveContents;
},
progresses(state) {
return state.progresses;
},
processing(state) {
return state.processing;
},
oerCampusEnabled(state, getters, rootState, rootGetters) {
return rootGetters['studip-properties/byId']({ id: 'oer-campus-enabled'}).attributes?.value;
},
oerEnableSuggestions(state, getters, rootState, rootGetters) {
return getters.oerCampusEnabled && rootGetters['studip-properties/byId']({ id: 'oer-enable-suggestions'}).attributes?.value;
},
toolbarActive(state) {
return state.toolbarActive;
},
hideEditLayout(state) {
return state.hideEditLayout;
},
feedbackSettings(state) {
return state.feedbackSettings;
},
isFeedbackActivated(state, getters) {
return getters.feedbackSettings?.activated ?? false;
},
canCreateFeedbackElement(state, getters) {
return getters.feedbackSettings?.createPerm ?? false;
},
canEditFeedbackElement(state, getters) {
return getters.feedbackSettings?.adminPerm ?? false;
},
};
export const state = { ...initialState };
export const actions = {
loadContainer({ dispatch }, containerId) {
const options = {
include: 'blocks,blocks.edit-blocker','fields[users]': 'formatted-name',
};
return dispatch('courseware-containers/loadById', { id: containerId, options }, { root: true });
},
loadStructuralElement({ dispatch }, structuralElementId) {
const options = {
include:
'containers,containers.edit-blocker,containers.blocks,containers.blocks.editor,containers.blocks.owner,containers.blocks.user-data-field,containers.blocks.user-progress,containers.blocks.edit-blocker,editor,edit-blocker,owner',
'fields[users]': 'formatted-name',
};
return dispatch(
'courseware-structural-elements/loadById',
{ id: structuralElementId, options },
{ root: true }
);
},
loadFileRefs({ dispatch, rootGetters }, block_id) {
const parent = {
type: 'courseware-blocks',
id: block_id,
};
const relationship = 'file-refs';
return dispatch('file-refs/loadRelated', { parent, relationship }, { root: true }).then(() =>
rootGetters['file-refs/related']({
parent,
relationship,
})
);
},
async loadUserDataFields({ dispatch }, blockId) {
const parent = { type: 'courseware-blocks', id: `${blockId}` };
const relationship = 'user-data-field';
const options = {
include: 'user',
};
return dispatch('user-data-field/loadRelated', { parent, relationship, options }, { root: true });
},
async loadCoursewareActivities({ dispatch, rootGetters }, { userId, courseId }) {
const parent = {
type: 'users',
id: userId,
};
const relationship = 'activitystream';
const options = {
'filter[context-type]': 'course',
'filter[context-id]': courseId,
'filter[object-type]': 'courseware',
include: 'actor, context, object',
};
await dispatch('users/loadRelated', { parent, relationship, options }, { root: true });
const activities = rootGetters['users/all'];
return activities.filter(({ type }) => type === 'activities');
},
async createFile(context, { file, filedata, folder }) {
const termId = file?.relationships?.['terms-of-use']?.data?.id ?? null;
const formData = new FormData();
formData.append('file', filedata, file.attributes.name);
if (termId) {
formData.append('term-id', termId);
}
const url = `folders/${folder.id}/file-refs`;
let request = await state.httpClient.post(url, formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
});
let response = null;
try {
response = await state.httpClient.get(request.headers.location);
}
catch(e) {
console.debug(e);
response = null;
}
return response ? response.data.data : response;
},
async updateFileContent(context, { file, filedata }) {
const url = `file-refs/${file.id}/content`;
const formData = new FormData();
formData.append('file', filedata, file.attributes.name);
let request = await state.httpClient.post(url, formData);
let response = null;
try {
response = await state.httpClient.get(request.headers.location);
}
catch(e) {
console.debug(e);
response = null;
}
return response ? response.data.data : response;
},
async createRootFolder({ dispatch, rootGetters }, { context, folder }) {
// get root folder for this context
await dispatch(
`${context.type}/loadRelated`,
{
parent: context,
relationship: 'folders',
},
{ root: true }
);
let folders = await rootGetters[`${context.type}/related`]({
parent: context,
relationship: 'folders',
});
let rootFolder = null;
for (let i = 0; i < folders.length; i++) {
if (folders[i].attributes['folder-type'] === 'RootFolder') {
rootFolder = folders[i];
}
}
const newFolder = {
data: {
type: 'folders',
attributes: {
name: folder.name,
'folder-type': 'StandardFolder',
},
relationships: {
parent: {
data: {
type: 'folders',
id: rootFolder.id,
},
},
},
},
};
return state.httpClient.post(`${context.type}/${context.id}/folders`, newFolder).then((response) => {
return response.data.data;
});
},
async createFolder(store, { context, parent, folder }) {
const newFolder = {
data: {
type: 'folders',
attributes: {
name: folder.name,
'folder-type': folder.type,
},
relationships: {
parent: parent,
},
},
};
return state.httpClient.post(`${context.type}/${context.id}/folders`, newFolder).then((response) => {
return response.data.data;
});
},
loadFolder({ dispatch }, folderId) {
const options = {};
return dispatch('folders/loadById', { id: folderId, options }, { root: true });
},
copyBlock({ getters }, { parentId, block, section }) {
const copy = {
data: {
block: block,
parent_id: parentId,
section: section
},
};
return state.httpClient.post(`courseware-blocks/${block.id}/copy`, copy).then((resp) => {
// console.log(resp);
});
},
clipboardInsertBlock({ getters }, { parentId, clipboard, section }) {
const insert = {
data: {
parent_id: parentId,
section: section
},
};
return state.httpClient.post(`courseware-clipboards/${clipboard.id}/insert`, insert);
},
copyContainer({ getters }, { parentId, container }) {
const copy = {
data: {
container: container,
parent_id: parentId,
},
};
return state.httpClient.post(`courseware-containers/${container.id}/copy`, copy).then((resp) => {
// console.log(resp);
});
},
clipboardInsertContainer({ getters },{ parentId, clipboard }) {
const insert = {
data: {
parent_id: parentId,
},
};
return state.httpClient.post(`courseware-clipboards/${clipboard.id}/insert`, insert);
},
async copyStructuralElement({ dispatch, getters, rootGetters }, { parentId, elementId, removePurpose, migrate, modifications }) {
const copy = { data: { parent_id: parentId, remove_purpose: removePurpose, migrate: migrate, modifications: modifications } };
const result = await state.httpClient.post(`courseware-structural-elements/${elementId}/copy`, copy);
const id = result.data.data.id;
await dispatch('loadStructuralElement', id);
const newElement = rootGetters['courseware-structural-elements/byId']({ id });
return dispatch('courseware-structure/loadDescendants', { root: newElement });
},
async linkStructuralElement({ dispatch, getters, rootGetters }, { parentId, elementId }) {
const link = { data: { parent_id: parentId } };
const result = await state.httpClient.post(`courseware-structural-elements/${elementId}/link`, link);
const id = result.data.data.id;
await dispatch('loadStructuralElement', id);
const newElement = rootGetters['courseware-structural-elements/byId']({ id });
return dispatch('courseware-structure/loadDescendants', { root: newElement });
},
async activateStructuralElementComments({ dispatch }, { element }) {
element.attributes.commentable = true;
const updatedElement = await dispatch('setStructuralElementComments', { element: element });
return updatedElement;
},
async deactivateStructuralElementComments({ dispatch }, { element }) {
element.attributes.commentable = false;
const updatedElement = await dispatch('setStructuralElementComments', { element: element });
return updatedElement;
},
async setStructuralElementComments({ dispatch }, { element }) {
await dispatch('lockObject', { id: element.id, type: 'courseware-structural-elements' });
const updatedElement = await dispatch('courseware-structural-elements/update', element, { root: true });
await dispatch('unlockObject', { id: element.id, type: 'courseware-structural-elements' });
return updatedElement;
},
async createBlockInContainer({ dispatch }, { container, blockType }) {
const block = {
attributes: {
'block-type': blockType,
payload: null,
},
relationships: {
container: {
data: { type: container.type, id: container.id },
},
},
};
await dispatch('courseware-blocks/create', block, { root: true });
return dispatch('loadContainer', container.id);
},
async deleteBlockInContainer({ dispatch }, { containerId, blockId }) {
const data = {
id: blockId,
};
await dispatch('courseware-blocks/delete', data, { root: true });
//TODO throws TypeError: block is undefined after delete
return dispatch('loadContainer', containerId);
},
async updateBlockInContainer({ dispatch }, { attributes, blockId, containerId }) {
const container = {
type: 'courseware-containers',
id: containerId,
};
const block = {
type: 'courseware-blocks',
attributes: attributes,
id: blockId,
relationships: {
container: {
data: { type: container.type, id: container.id },
},
},
};
await dispatch('courseware-blocks/update', block, { root: true });
await dispatch('unlockObject', { id: blockId, type: 'courseware-blocks' });
return dispatch('loadContainer', containerId);
},
async updateBlock({ dispatch }, { block, containerId }) {
const container = {
type: 'courseware-containers',
id: containerId,
};
const updateBlock = {
type: 'courseware-blocks',
attributes: block.attributes,
id: block.id,
relationships: {
container: {
data: { type: container.type, id: container.id },
},
},
};
await dispatch('courseware-blocks/update', updateBlock, { root: true });
return dispatch('loadContainer', containerId);
},
async deleteBlock({ dispatch }, { containerId, blockId }) {
const data = {
id: blockId,
};
await dispatch('courseware-blocks/delete', data, { root: true });
//TODO throws TypeError: block is undefined after delete
return dispatch('loadContainer', containerId);
},
async activateBlockComments({ dispatch }, { block }) {
block.attributes.commentable = true;
const updatedBlock = await dispatch('setBlockComments', { block: block });
return updatedBlock;
},
async deactivateBlockComments({ dispatch }, { block }) {
block.attributes.commentable = false;
const updatedBlock = await dispatch('setBlockComments', { block: block });
return updatedBlock;
},
async setBlockComments({ dispatch }, { block }) {
await dispatch('lockObject', { id: block.id, type: 'courseware-blocks' });
const updatedBlock = await dispatch('courseware-blocks/update', block, { root: true });
await dispatch('unlockObject', { id: block.id, type: 'courseware-blocks' });
return updatedBlock;
},
async storeCoursewareSettings({ dispatch, getters },
{ permission, progression, certificateSettings, reminderSettings,
resetProgressSettings }) {
const courseware = getters.courseware;
courseware.attributes['editing-permission-level'] = permission;
courseware.attributes['sequential-progression'] = progression;
courseware.attributes['certificate-settings'] = certificateSettings;
courseware.attributes['reminder-settings'] = reminderSettings;
courseware.attributes['reset-progress-settings'] = resetProgressSettings;
return dispatch('courseware-instances/update', courseware, { root: true });
},
sortChildrenInStructualElements({ dispatch }, { parent, children }) {
const childrenResourceIdentifiers = children.map(({ type, id }) => ({ type, id }));
return dispatch(
`courseware-structural-elements/setRelated`,
{
parent: { type: parent.type, id: parent.id },
relationship: 'children',
data: childrenResourceIdentifiers,
},
{ root: true }
).then(() => dispatch(
`${parent.type}/loadRelated`,
{
parent: { type: parent.type, id: parent.id },
relationship: 'children',
},
{ root: true }
)).then(() => dispatch('courseware-structure/build', null, { root: true }));
},
async createStructuralElement({ dispatch }, { attributes, parentId, currentId }) {
const data = {
attributes,
relationships: {
parent: {
data: {
type: 'courseware-structural-elements',
id: parentId,
},
},
},
};
await dispatch('courseware-structural-elements/create', data, { root: true });
return dispatch('loadStructuralElement', currentId);
},
async createStructuralElementWithTemplate({ dispatch }, { attributes, parentId, currentId, templateId }) {
const data = {
attributes,
relationships: {
parent: {
data: {
type: 'courseware-structural-elements',
id: parentId,
},
},
},
templateId: templateId,
};
await dispatch('courseware-structural-elements/create', data, { root: true });
const options = {
include: 'children',
};
return dispatch('courseware-structural-elements/loadById', { id: currentId, options }, { root: true });
},
async deleteStructuralElement({ dispatch }, { id, parentId }) {
const data = {
id: id,
};
await dispatch('courseware-structural-elements/delete', data, { root: true });
return dispatch('loadStructuralElement', parentId);
},
async updateStructuralElement({ dispatch }, { element, id }) {
await dispatch('courseware-structural-elements/update', element, { root: true });
return dispatch('loadStructuralElement', id);
},
sortContainersInStructualElements({ dispatch }, { structuralElement, containers }) {
const containerResourceIdentifiers = containers.map(({ type, id }) => ({ type, id }));
return dispatch(
`courseware-structural-elements/setRelated`,
{
parent: { type: structuralElement.type, id: structuralElement.id },
relationship: 'containers',
data: containerResourceIdentifiers,
},
{ root: true }
);
},
async createContainer({ dispatch }, { attributes, structuralElementId }) {
const data = {
attributes,
relationships: {
'structural-element': {
data: {
type: 'courseware-structural-elements',
id: structuralElementId,
},
},
},
};
await dispatch('courseware-containers/create', data, { root: true });
return dispatch('loadStructuralElement', structuralElementId);
},
async deleteContainer({ dispatch }, { containerId, structuralElementId }) {
const data = {
id: containerId,
};
await dispatch('courseware-containers/delete', data, { root: true });
//TODO throws TypeError: container is undefined after delete
return dispatch('loadStructuralElement', structuralElementId);
},
async updateContainer({ dispatch }, { container, structuralElementId }) {
await dispatch('courseware-containers/update', container, { root: true });
return dispatch('loadStructuralElement', structuralElementId);
},
sortBlocksInContainer({ dispatch }, { container, sections }) {
let blockResourceIdentifiers = [];
sections.forEach((section) => {
blockResourceIdentifiers.push(...section.blocks.map(({ type, id }) => ({ type, id })));
});
return dispatch(
`courseware-containers/setRelated`,
{
parent: { type: container.type, id: container.id },
relationship: 'blocks',
data: blockResourceIdentifiers,
},
{ root: true }
);
},
lockObject({ dispatch, getters }, { id, type }) {
return dispatch(`${type}/setRelated`, {
parent: { id, type },
relationship: 'edit-blocker',
data: {
type: 'users',
id: getters.userId,
},
});
},
unlockObject({ dispatch }, { id, type }) {
return dispatch(`${type}/setRelated`, {
parent: { id, type },
relationship: 'edit-blocker',
data: null,
});
},
async companionInfo({ dispatch }, { info }) {
STUDIP.eventBus.emit('push-system-notification', { type: 'info', message: info});
},
async companionSuccess({ dispatch }, { info }) {
STUDIP.eventBus.emit('push-system-notification', { type: 'success', message: info});
},
async companionError({ dispatch }, { info }) {
STUDIP.eventBus.emit('push-system-notification', { type: 'error', message: info});
},
async companionWarning({ dispatch }, { info }) {
STUDIP.eventBus.emit('push-system-notification', { type: 'exception', message: info});
},
async companionSpecial({ dispatch }, { info }) {
STUDIP.eventBus.emit('push-system-notification', { type: 'warning', message: info});
},
// adds a favorite block type using the `type` of the BlockType
async addFavoriteBlockType({ dispatch, getters }, blockType) {
const blockTypes = new Set(getters.favoriteBlockTypes.map(({ type }) => type));
blockTypes.add(blockType);
return dispatch('storeFavoriteBlockTypes', [...blockTypes]);
},
// removes a favorite block type using the `type` of the BlockType
async removeFavoriteBlockType({ dispatch, getters }, blockType) {
const blockTypes = new Set(getters.favoriteBlockTypes.map(({ type }) => type));
blockTypes.delete(blockType);
return dispatch('storeFavoriteBlockTypes', [...blockTypes]);
},
// sets the favorite block types using an array of the `type`s of those BlockTypes
async storeFavoriteBlockTypes({ dispatch, getters }, favoriteBlockTypes) {
const courseware = getters.courseware;
courseware.attributes['favorite-block-types'] = favoriteBlockTypes;
return dispatch('courseware-instances/update', courseware, { root: true });
},
coursewareCurrentElement(context, id) {
context.commit('coursewareCurrentElementSet', id);
},
coursewareContext(context, id) {
context.commit('coursewareContextSet', id);
},
licenses(context, licenses) {
context.commit('licensesSet', licenses);
},
coursewareViewMode(context, view) {
context.commit('coursewareViewModeSet', view);
},
setDashboardViewMode(context, view) {
context.commit('setDashboardViewMode', view);
},
coursewareShowToolbar(context, toolbar) {
context.commit('coursewareShowToolbarSet', toolbar);
},
coursewareSelectedToolbarItem(context, item) {
context.commit('coursewareSelectedToolbarItemSet', item);
},
coursewareBlockAdder(context, adder) {
context.commit('coursewareBlockAdderSet', adder);
},
coursewareContainerAdder(context, adder) {
context.commit('coursewareContainerAdderSet', adder);
},
coursewareShowCompanionOverlay(context, companion_overlay) {
context.commit('coursewareShowCompanionOverlaySet', companion_overlay);
},
coursewareMsgCompanionOverlay(context, companion_overlay_msg) {
context.commit('coursewareMsgCompanionOverlaySet', companion_overlay_msg);
},
coursewareStyleCompanionOverlay(context, companion_overlay_style) {
context.commit('coursewareStyleCompanionOverlaySet', companion_overlay_style);
},
coursewareConsumeMode(context, mode) {
context.commit('coursewareConsumeModeSet', mode);
},
setHttpClient({ commit }, httpClient) {
commit('setHttpClient', httpClient);
},
setUrlHelper({ commit }, urlHelper) {
commit('setUrlHelper', urlHelper);
},
setUserId({ commit }, userId) {
commit('setUserId', userId);
},
showElementEditDialog(context, bool) {
context.commit('setShowStructuralElementEditDialog', bool);
},
showElementAddDialog(context, bool) {
context.commit('setShowStructuralElementAddDialog', bool);
},
showElementAddChooserDialog(context, bool) {
context.commit('setShowStructuralElementAddChooserDialog', bool);
},
showElementImportDialog(context, bool) {
context.commit('setShowStructuralElementImportDialog', bool);
},
showElementCopyDialog(context, bool) {
context.commit('setShowStructuralElementCopyDialog', bool);
},
showElementLinkDialog(context, bool) {
context.commit('setShowStructuralElementLinkDialog', bool);
},
showElementExportDialog(context, bool) {
context.commit('setShowStructuralElementExportDialog', bool);
},
showElementExportChooserDialog(context, bool) {
context.commit('setShowStructuralElementExportChooserDialog', bool);
},
showElementPdfExportDialog(context, bool) {
context.commit('setShowStructuralElementPdfExportDialog', bool);
},
showElementInfoDialog(context, bool) {
context.commit('setShowStructuralElementInfoDialog', bool);
},
showElementOerDialog(context, bool) {
context.commit('setShowStructuralElementOerDialog', bool);
},
updateShowSuggestOerDialog(context, bool) {
context.commit('setShowSuggestOerDialog', bool);
},
showElementDeleteDialog(context, bool) {
context.commit('setShowStructuralElementDeleteDialog', bool);
},
showElementPublicLinkDialog(context, bool) {
context.commit('setShowStructuralElementPublicLinkDialog', bool);
},
showElementRemoveLockDialog(context, bool) {
context.commit('setShowStructuralElementRemoveLockDialog', bool);
},
showStructuralElementFeedbackDialog(context, bool) {
context.commit('setShowStructuralElementFeedbackDialog', bool);
},
showStructuralElementFeedbackCreateDialog(context, bool) {
context.commit('setShowStructuralElementFeedbackCreateDialog', bool);
},
setShowOverviewElementAddDialog(context, bool) {
context.commit('setShowOverviewElementAddDialog', bool);
},
setImportFilesState({ commit }, state) {
commit('setImportFilesState', state);
},
setImportFilesProgress({ commit }, percent) {
commit('setImportFilesProgress', percent);
},
setImportStructuresState({ commit }, state) {
commit('setImportStructuresState', state);
},
setImportStructuresProgress({ commit }, percent) {
commit('setImportStructuresProgress', percent);
},
setImportErrors({ commit }, errors) {
commit('setImportErrors', errors);
},
setExportState({ commit }, state) {
commit('setExportState', state);
},
setExportProgress({ commit }, percent) {
commit('setExportProgress', percent);
},
setShowSearchResults({ commit }, state) {
commit('setShowSearchResults', state);
},
setSearchResults({ commit }, state) {
commit('setSearchResults', state);
},
setAssistiveLiveContents({ commit }, state) {
commit('setAssistiveLiveContents', state);
},
setUserIsTeacherInCourse({ commit }, state) {
commit('setUserIsTeacherInCourse', state);
},
addBookmark({ dispatch, rootGetters }, structuralElement) {
const cw = rootGetters['courseware'];
// get existing bookmarks
const bookmarks =
rootGetters['courseware-structural-elements/related']({
parent: cw,
relationship: 'bookmarks',
})?.map(({ type, id }) => ({ type, id })) ?? [];
// add a new bookmark
const data = [...bookmarks, { type: structuralElement.type, id: structuralElement.id }];
// send them home
return dispatch(
`courseware-structural-elements/setRelated`,
{
parent: { type: cw.type, id: cw.id },
relationship: 'bookmarks',
data,
},
{ root: true }
);
},
removeBookmark({ dispatch, rootGetters }, structuralElement) {
const cw = rootGetters['courseware'];
// get existing bookmarks
const bookmarks =
rootGetters['courseware-structural-elements/related']({
parent: cw,
relationship: 'bookmarks',
})?.map(({ type, id }) => ({ type, id })) ?? [];
// filter bookmark that must be removed
const data = bookmarks.filter(({ id }) => id !== structuralElement.id);
// send them home
return dispatch(
`courseware-structural-elements/setRelated`,
{
parent: { type: cw.type, id: cw.id },
relationship: 'bookmarks',
data,
},
{ root: true }
);
},
setPluginManager({ commit }, pluginManager) {
commit('setPluginManager', pluginManager);
},
uploadImageForStructuralElement({ dispatch, state }, { structuralElement, file }) {
const formData = new FormData();
formData.append('image', file);
const url = `courseware-structural-elements/${structuralElement.id}/image`;
return state.httpClient.post(url, formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
});
},
setStockImageForStructuralElement({ dispatch, state }, { structuralElement, stockImage }) {
const { id, type } = structuralElement;
structuralElement.relationships.image = { data: { type: 'stock-images', id: stockImage.id } };
return dispatch('lockObject', { id, type })
.then(() => dispatch('updateStructuralElement', { element: structuralElement, id }))
.then(() => dispatch('lockObject', { id, type }));
},
async deleteImageForStructuralElement({ dispatch, state }, structuralElement) {
const url = `courseware-structural-elements/${structuralElement.id}/image`;
await state.httpClient.delete(url);
return dispatch('loadStructuralElement', structuralElement.id);
},
async loadRelatedPaginated({ dispatch, rootGetters }, { type, parent, relationship, options }) {
const limit = 100;
let offset = 0;
await loadPage(offset, limit);
const total = rootGetters[`${type}/lastMeta`].page.total;
const pages = [];
for (let page = 1; page * limit < total; page++) {
pages.push(loadPage(page * limit, limit));
}
return Promise.all(pages);
function loadPage(offset, limit) {
return dispatch(
`${type}/loadRelated`,
{
parent,
relationship,
options: {
...options,
'page[offset]': offset,
'page[limit]': limit,
},
resetRelated: false,
},
{ root: true }
)
}
},
loadUsersBookmarks({ dispatch, rootGetters, state }, userId) {
const parent = {
type: 'users',
id: userId,
};
const relationship = 'courseware-bookmarks';
const options = {
include: 'course',
};
return dispatch('loadRelatedPaginated', {
type: 'courseware-structural-elements',
parent,
relationship,
options,
});
},
async loadUsersCourses({ dispatch, rootGetters, state }, { userId, withCourseware }) {
const parent = {
type: 'users',
id: userId,
};
const relationship = 'course-memberships';
const options = {
include: 'course',
};
await dispatch('loadRelatedPaginated', {
type: 'course-memberships',
parent,
relationship,
options,
});
const memberships = rootGetters['course-memberships/related']({
parent,
relationship,
});
const otherMemberships = memberships.filter(({ attributes, relationships }) => {
return ['dozent', 'tutor'].includes(attributes.permission);
});
if (!withCourseware) {
return otherMemberships.map((membership) => {
return getCourse(membership);
});
}
const items = otherMemberships.map((membership) => {
let course = getCourse(membership);
course['userPermission'] = membership.attributes.permission;
return { membership, course };
});
return items
.filter(({ membership, course }) => {
return course.relationships.courseware.data;
})
.map(({ course }) => course);
function getCourse(membership) {
return rootGetters['courses/related']({ parent: membership, relationship: 'course' });
}
},
async loadRemoteCoursewareStructure({ dispatch, rootGetters }, { rangeId, rangeType }) {
const parent = {
id: rangeId,
type: rangeType,
};
const relationship = 'courseware';
return dispatch(`courseware-instances/loadRelated`, { parent, relationship }, { root: true }).then(
(response) => {
const instance = rootGetters['courseware-instances/related']({
parent: parent,
relationship: relationship,
});
return instance;
},
(error) => {
return null;
}
);
},
loadFeedback({ dispatch }, blockId) {
const parent = { type: 'courseware-blocks', id: `${blockId}` };
const relationship = 'feedback';
const options = {
include: 'user',
};
return dispatch('courseware-block-feedback/loadRelated', { parent, relationship, options }, { root: true });
},
async createFeedback({ dispatch }, { blockId, feedback }) {
const data = {
attributes: {
feedback,
},
relationships: {
block: {
data: {
type: 'courseware-blocks',
id: blockId,
},
},
},
};
await dispatch('courseware-block-feedback/create', data, { root: true });
return dispatch('loadFeedback', blockId);
},
async createTaskGroup({ dispatch, rootGetters }, { taskGroup }) {
await dispatch('courseware-task-groups/create', taskGroup, { root: true });
const id = taskGroup.relationships.target.data.id;
const target = rootGetters['courseware-structural-elements/byId']({ id });
return dispatch('courseware-structure/loadDescendants', { root: target });
},
async loadTask({ dispatch }, { taskId }) {
return dispatch(
'courseware-tasks/loadById',
{
id: taskId,
options: {
include: 'solver,task-group,task-group.lecturer',
},
},
{ root: true }
).catch(error => console.debug(error));
},
async updateTask({ dispatch }, { attributes, taskId }) {
const task = {
type: 'courseware-tasks',
attributes: attributes,
id: taskId,
};
await dispatch('courseware-tasks/update', task, { root: true });
return dispatch('loadTask', { taskId: task.id });
},
async deleteTask({ dispatch }, { task }) {
const data = {
id: task.id,
};
await dispatch('courseware-tasks/delete', data, { root: true });
},
async createTaskFeedback({ dispatch }, { taskFeedback }) {
await dispatch('courseware-task-feedback/create', taskFeedback, { root: true });
return dispatch('loadTask', { taskId: taskFeedback.relationships.task.data.id });
},
async updateTaskFeedback({ dispatch }, { attributes, taskFeedbackId }) {
const taskFeedback = {
type: 'courseware-task-feedback',
attributes: attributes,
id: taskFeedbackId,
};
await dispatch('courseware-task-feedback/update', taskFeedback, { root: true });
return dispatch('courseware-task-feedback/loadById', { id: taskFeedback.id }, { root: true });
},
async deleteTaskFeedback({ dispatch }, { taskFeedbackId }) {
const data = {
id: taskFeedbackId,
};
await dispatch('courseware-task-feedback/delete', data, { root: true });
},
setPermissionFilter({ commit }, permission) {
commit('setPermissionFilter', permission);
},
setPurposeFilter({ commit }, purpose) {
commit('setPurposeFilter', purpose);
},
setSourceFilter({ commit }, source) {
commit('setSourceFilter', source);
},
setBookmarkFilter({ commit }, course) {
commit('setBookmarkFilter', course);
},
setProcessing({ commit }, processing) {
commit('setProcessing', processing);
},
createLink({ dispatch, rootGetters }, { publicLink }) {
dispatch('courseware-public-links/create', publicLink, { root: true });
},
deleteLink({ dispatch }, { linkId }) {
const data = {
id: linkId,
};
dispatch('courseware-public-links/delete', data, { root: true });
},
async updateLink({ dispatch }, { attributes, linkId }) {
const link = {
type: 'courseware-public-links',
attributes: attributes,
id: linkId,
};
await dispatch('courseware-public-links/update', link, { root: true });
return dispatch('courseware-public-links/loadById', { id: link.id }, { root: true });
},
loadCourseUnits({ dispatch }, cid) {
const parent = { type: 'courses', id: cid };
const relationship = 'courseware-units';
const options = { include: 'structural-element' }
return dispatch('loadRelatedPaginated', {
type: 'courseware-units',
parent,
relationship,
options,
});
},
loadUserUnits({ dispatch }, uid) {
const parent = { type: 'users', id: uid };
const relationship = 'courseware-units';
const options = { include: 'structural-element' }
return dispatch('loadRelatedPaginated', {
type: 'courseware-units',
parent,
relationship,
options,
});
},
async loadUnitProgresses({ getters }, { unitId }) {
const response = await state.httpClient.get(`courseware-units/${unitId}/courseware-user-progresses`);
if (response.status === 200) {
return response.data;
} else {
return null;
}
},
async loadProgresses({ dispatch, commit, getters }) {
const progresses = await dispatch('loadUnitProgresses', { unitId: getters.context.unit });
commit('setProgresses', progresses);
},
loadUserClipboards({ dispatch }, uid) {
dispatch('courseware-clipboards/resetState');
const parent = { type: 'users', id: uid };
const relationship = 'courseware-clipboards';
const options = {}
return dispatch('loadRelatedPaginated', {
type: 'courseware-clipboards',
parent,
relationship,
options,
});
},
async deleteUserClipboards({ dispatch, rootGetters }, { uid, type }) {
await state.httpClient.delete(`users/${uid}/courseware-clipboards/${type}`);
dispatch('loadUserClipboards', uid);
},
toggleToolbarActive({ commit, rootGetters }) {
if (!rootGetters['toolbarActive']) {
commit('setHideEditLayout', false);
}
commit('setToolbarActive', !rootGetters['toolbarActive']);
},
toggleHideEditLayout({ commit, rootGetters}) {
commit('setHideEditLayout', !rootGetters['hideEditLayout']);
},
setHideEditLayout({commit}, state) {
commit('setHideEditLayout', state);
},
setFeedbackSettings(context, feedbackSettings) {
context.commit('setFeedbackSettings', feedbackSettings);
},
};
/* eslint no-param-reassign: ["error", { "props": false }] */
export const mutations = {
coursewareSet(state, data) {
state.courseware = data;
},
coursewareCurrentElementSet(state, data) {
state.lastElement = state.currentElement;
state.currentElement = data;
},
coursewareContextSet(state, data) {
state.context = data;
},
licensesSet(state, data) {
state.licenses = data;
},
coursewareViewModeSet(state, data) {
state.viewMode = data;
},
setDashboardViewMode(state, data) {
state.dashboardViewMode = data;
},
coursewareShowToolbarSet(state, data) {
state.showToolbar = data;
},
coursewareSelectedToolbarItemSet(state, data) {
state.selectedToolbarItem = data;
},
coursewareBlockAdderSet(state, data) {
state.blockAdder = data;
},
coursewareContainerAdderSet(state, data) {
state.containerAdder = data;
},
coursewareShowCompanionOverlaySet(state, data) {
state.showCompanionOverlay = data;
},
coursewareMsgCompanionOverlaySet(state, data) {
state.msgCompanionOverlay = data;
},
coursewareStyleCompanionOverlaySet(state, data) {
state.styleCompanionOverlay = data;
},
coursewareConsumeModeSet(state, data) {
state.consumeMode = data;
},
setHttpClient(state, httpClient) {
state.httpClient = httpClient;
},
setUrlHelper(state, urlHelper) {
state.urlHelper = urlHelper;
},
setUserId(state, userId) {
state.userId = userId;
},
setPluginManager(state, pluginManager) {
state.pluginManager = pluginManager;
},
setShowStructuralElementEditDialog(state, showEdit) {
state.showStructuralElementEditDialog = showEdit;
},
setShowStructuralElementAddDialog(state, showAdd) {
state.showStructuralElementAddDialog = showAdd;
},
setShowStructuralElementAddChooserDialog(state, showAddChooser) {
state.showStructuralElementAddChooserDialog = showAddChooser;
},
setShowStructuralElementImportDialog(state, showImport) {
state.showStructuralElementImportDialog = showImport;
},
setShowStructuralElementCopyDialog(state, showCopy) {
state.showStructuralElementCopyDialog = showCopy;
},
setShowStructuralElementLinkDialog(state, showLink) {
state.showStructuralElementLinkDialog = showLink;
},
setShowStructuralElementExportDialog(state, showExport) {
state.showStructuralElementExportDialog = showExport;
},
setShowStructuralElementExportChooserDialog(state, showExportChooser) {
state.showStructuralElementExportChooserDialog = showExportChooser;
},
setShowStructuralElementPdfExportDialog(state, showPdfExport) {
state.showStructuralElementPdfExportDialog = showPdfExport;
},
setShowStructuralElementInfoDialog(state, showInfo) {
state.showStructuralElementInfoDialog = showInfo;
},
setShowSuggestOerDialog(state, showSuggest) {
state.showSuggestOerDialog = showSuggest;
},
setShowStructuralElementOerDialog(state, showOer) {
state.showStructuralElementOerDialog = showOer;
},
setShowStructuralElementDeleteDialog(state, showDelete) {
state.showStructuralElementDeleteDialog = showDelete;
},
setShowOverviewElementAddDialog(state, showAdd) {
state.showOverviewElementAddDialog = showAdd;
},
setShowStructuralElementPublicLinkDialog(state, showPublicLink) {
state.showStructuralElementPublicLinkDialog = showPublicLink;
},
setShowStructuralElementRemoveLockDialog(state, showRemoveLock) {
state.showStructuralElementRemoveLockDialog = showRemoveLock;
},
setShowStructuralElementFeedbackDialog(state, showFeedback) {
state.showStructuralElementFeedbackDialog = showFeedback;
},
setShowStructuralElementFeedbackCreateDialog(state, showFeedbackCreate) {
state.showStructuralElementFeedbackCreateDialog = showFeedbackCreate;
},
setImportFilesState(state, importFilesState) {
state.importFilesState = importFilesState;
},
setImportFilesProgress(state, importFilesProgress) {
state.importFilesProgress = importFilesProgress;
},
setImportErrors(state, importErrors) {
state.importErrors = importErrors;
},
setImportStructuresState(state, importStructuresState) {
state.importStructuresState = importStructuresState;
},
setImportStructuresProgress(state, importStructuresProgress) {
state.importStructuresProgress = importStructuresProgress;
},
setExportState(state, exportState) {
state.exportState = exportState;
},
setExportProgress(state, exportProgress) {
state.exportProgress = exportProgress;
},
setPermissionFilter(state, permission) {
state.permissionFilter = permission;
},
setPurposeFilter(state, purpose) {
state.purposeFilter = purpose;
},
setSourceFilter(state, source) {
state.sourceFilter = source;
},
setBookmarkFilter(state, course) {
state.bookmarkFilter = course;
},
setShowSearchResults(state, searchState) {
state.showSearchResults = searchState;
},
setSearchResults(state, results) {
state.searchResults = results;
},
setAssistiveLiveContents(state, text) {
state.assistiveLiveContents = text;
},
setUserIsTeacherInCourse(state, isTeacher) {
state.userIsTeacherInCourse = isTeacher;
},
setProgresses(state, data) {
state.progresses = data;
},
setToolbarActive(state, active) {
state.toolbarActive = active;
},
setHideEditLayout(state, hide) {
state.hideEditLayout = hide;
},
setFeedbackSettings(state, feedbackSettings) {
state.feedbackSettings = feedbackSettings;
},
setProcessing(state, processing) {
state.processing = processing;
}
};
export default {
state,
actions,
mutations,
getters,
};