Commit a994b73c authored by Paul Slaughter's avatar Paul Slaughter

Add editor module

This module is used to house properties for files opened
during the lifetime of the IDE.

Currently we store these properties for every
file, even folders which is very wasteful.
parent 8bd8ea37
import * as types from './mutation_types';
/**
* Action to update the current file editor info at the given `path` with the given `data`
*
* @param {} vuex
* @param {{ path: String, data: any }} payload
*/
export const updateFileEditor = ({ commit }, payload) => {
commit(types.UPDATE_FILE_EDITOR, payload);
};
export const removeFileEditor = ({ commit }, path) => {
commit(types.REMOVE_FILE_EDITOR, path);
};
import { getFileEditorOrDefault } from './utils';
export const activeFileEditor = (state, getters, rootState, rootGetters) => {
const { activeFile } = rootGetters;
if (!activeFile) {
return null;
}
const { path } = rootGetters.activeFile;
return getFileEditorOrDefault(state.fileEditors, path);
};
import * as actions from './actions';
import * as getters from './getters';
import state from './state';
import mutations from './mutations';
export default {
namespaced: true,
actions,
state,
mutations,
getters,
};
export const UPDATE_FILE_EDITOR = 'UPDATE_FILE_EDITOR';
export const REMOVE_FILE_EDITOR = 'REMOVE_FILE_EDITOR';
import Vue from 'vue';
import * as types from './mutation_types';
import { getFileEditorOrDefault } from './utils';
export default {
[types.UPDATE_FILE_EDITOR](state, { path, data }) {
const editor = getFileEditorOrDefault(state.fileEditors, path);
Vue.set(state.fileEditors, path, Object.assign(editor, data));
},
[types.REMOVE_FILE_EDITOR](state, path) {
Vue.delete(state.fileEditors, path);
},
};
import eventHub from '~/ide/eventhub';
const removeUnusedFileEditors = store => {
Object.keys(store.state.editor.fileEditors)
.filter(path => !store.state.entries[path])
.forEach(path => store.dispatch('editor/removeFileEditor', path));
};
export const setupFileEditorsSync = store => {
eventHub.$on('ide.files.change', () => {
removeUnusedFileEditors(store);
});
};
export default () => ({
// Object which represents a dictionary of filePath to editor specific properties, including:
// - fileLanguage
// - editorRow
// - editorCol
// - viewMode
fileEditors: {},
});
import { FILE_VIEW_MODE_EDITOR } from '../../../constants';
export const createDefaultFileEditor = () => ({
editorRow: 1,
editorColumn: 1,
fileLanguage: '',
viewMode: FILE_VIEW_MODE_EDITOR,
});
export const getFileEditorOrDefault = (fileEditors, path) =>
fileEditors[path] || createDefaultFileEditor();
import testAction from 'helpers/vuex_action_helper';
import * as types from '~/ide/stores/modules/editor/mutation_types';
import * as actions from '~/ide/stores/modules/editor/actions';
describe('~/ide/stores/modules/editor/actions', () => {
describe('updateFileEditor', () => {
it('commits with payload', () => {
const payload = {};
testAction(actions.updateFileEditor, payload, {}, [
{ type: types.UPDATE_FILE_EDITOR, payload },
]);
});
});
describe('removeFileEditor', () => {
it('commits with payload', () => {
const payload = 'path/to/file.txt';
testAction(actions.removeFileEditor, payload, {}, [
{ type: types.REMOVE_FILE_EDITOR, payload },
]);
});
});
});
import { createDefaultFileEditor } from '~/ide/stores/modules/editor/utils';
import * as getters from '~/ide/stores/modules/editor/getters';
const TEST_PATH = 'test/path.md';
const TEST_FILE_EDITOR = {
...createDefaultFileEditor(),
editorRow: 7,
editorColumn: 8,
fileLanguage: 'markdown',
};
describe('~/ide/stores/modules/editor/getters', () => {
describe('activeFileEditor', () => {
it.each`
activeFile | fileEditors | expected
${null} | ${{}} | ${null}
${{}} | ${{}} | ${createDefaultFileEditor()}
${{ path: TEST_PATH }} | ${{}} | ${createDefaultFileEditor()}
${{ path: TEST_PATH }} | ${{ bogus: createDefaultFileEditor(), [TEST_PATH]: TEST_FILE_EDITOR }} | ${TEST_FILE_EDITOR}
`(
'with activeFile=$activeFile and fileEditors=$fileEditors',
({ activeFile, fileEditors, expected }) => {
const rootGetters = { activeFile };
const state = { fileEditors };
const result = getters.activeFileEditor(state, {}, {}, rootGetters);
expect(result).toEqual(expected);
},
);
});
});
import { createDefaultFileEditor } from '~/ide/stores/modules/editor/utils';
import * as types from '~/ide/stores/modules/editor/mutation_types';
import mutations from '~/ide/stores/modules/editor/mutations';
const TEST_PATH = 'test/path.md';
describe('~/ide/stores/modules/editor/mutations', () => {
describe(types.UPDATE_FILE_EDITOR, () => {
it('with path that does not exist, should initialize with default values', () => {
const state = { fileEditors: {} };
const data = { fileLanguage: 'markdown' };
mutations[types.UPDATE_FILE_EDITOR](state, { path: TEST_PATH, data });
expect(state.fileEditors).toEqual({
[TEST_PATH]: {
...createDefaultFileEditor(),
...data,
},
});
});
it('with existing path, should overwrite values', () => {
const state = {
fileEditors: {
foo: {},
[TEST_PATH]: { ...createDefaultFileEditor(), editorRow: 7, editorColumn: 7 },
},
};
mutations[types.UPDATE_FILE_EDITOR](state, {
path: TEST_PATH,
data: { fileLanguage: 'markdown' },
});
expect(state).toEqual({
fileEditors: {
foo: {},
[TEST_PATH]: {
...createDefaultFileEditor(),
editorRow: 7,
editorColumn: 7,
fileLanguage: 'markdown',
},
},
});
});
});
describe(types.REMOVE_FILE_EDITOR, () => {
it.each`
fileEditors | path | expected
${{}} | ${'does/not/exist.txt'} | ${{}}
${{ foo: {}, [TEST_PATH]: {} }} | ${TEST_PATH} | ${{ foo: {} }}
`('removes file $path', ({ fileEditors, path, expected }) => {
const state = { fileEditors };
mutations[types.REMOVE_FILE_EDITOR](state, path);
expect(state).toEqual({ fileEditors: expected });
});
});
});
import Vuex from 'vuex';
import eventHub from '~/ide/eventhub';
import { createStoreOptions } from '~/ide/stores';
import { setupFileEditorsSync } from '~/ide/stores/modules/editor/setup';
describe('~/ide/stores/modules/editor/setup', () => {
it('when files change is emitted, removes unused fileEditors', async () => {
const store = new Vuex.Store(createStoreOptions());
store.state.entries = {
foo: {},
bar: {},
};
store.state.editor.fileEditors = {
foo: {},
bizz: {},
};
setupFileEditorsSync(store);
eventHub.$emit('ide.files.change');
expect(store.state.entries).toEqual({
foo: {},
bar: {},
});
expect(store.state.editor.fileEditors).toEqual({
foo: {},
});
});
});
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment