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
24 changes: 13 additions & 11 deletions src/commons/sagas/MainSaga.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { SagaIterator } from 'redux-saga';
import { fork } from 'redux-saga/effects';
import { all, fork } from 'redux-saga/effects';

import { mockBackendSaga } from '../mocks/BackendMocks';
import Constants from '../utils/Constants';
Expand All @@ -15,14 +15,16 @@ import StoriesSaga from './StoriesSaga';
import WorkspaceSaga from './WorkspaceSaga';

export default function* MainSaga(): SagaIterator {
yield fork(Constants.useBackend ? BackendSaga : mockBackendSaga);
yield fork(WorkspaceSaga);
yield fork(LoginSaga);
yield fork(PlaygroundSaga);
yield fork(AchievementSaga);
yield fork(PersistenceSaga);
yield fork(GitHubPersistenceSaga);
yield fork(RemoteExecutionSaga);
yield fork(StoriesSaga);
yield fork(SideContentSaga);
yield all([
fork(Constants.useBackend ? BackendSaga : mockBackendSaga),
fork(WorkspaceSaga),
fork(LoginSaga),
fork(PlaygroundSaga),
fork(AchievementSaga),
fork(PersistenceSaga),
fork(GitHubPersistenceSaga),
fork(RemoteExecutionSaga),
fork(StoriesSaga),
fork(SideContentSaga)
]);
}
2 changes: 1 addition & 1 deletion src/commons/workspace/WorkspaceActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ export const browseReplHistoryUp = createAction(

export const changeExternalLibrary = createAction(
CHANGE_EXTERNAL_LIBRARY,
(newExternal: string, workspaceLocation: WorkspaceLocation) => ({
(newExternal: ExternalLibraryName, workspaceLocation: WorkspaceLocation) => ({
payload: { newExternal, workspaceLocation }
})
);
Expand Down
222 changes: 97 additions & 125 deletions src/commons/workspace/WorkspaceReducer.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { createReducer } from '@reduxjs/toolkit';
import { stringify } from 'js-slang/dist/utils/stringify';
import { Reducer } from 'redux';

Expand Down Expand Up @@ -33,16 +34,19 @@ import { NOTIFY_PROGRAM_EVALUATED } from '../sideContent/SideContentTypes';
import { SourceActionType } from '../utils/ActionsHelper';
import Constants from '../utils/Constants';
import { createContext } from '../utils/JsSlangHelper';
import {
browseReplHistoryDown,
browseReplHistoryUp,
changeExecTime,
changeStepLimit,
clearReplInput,
clearReplOutput,
clearReplOutputLast,
setTokenCount
} from './WorkspaceActions';
import {
ADD_EDITOR_TAB,
BROWSE_REPL_HISTORY_DOWN,
BROWSE_REPL_HISTORY_UP,
CHANGE_EXEC_TIME,
CHANGE_EXTERNAL_LIBRARY,
CHANGE_STEP_LIMIT,
CLEAR_REPL_INPUT,
CLEAR_REPL_OUTPUT,
CLEAR_REPL_OUTPUT_LAST,
DISABLE_TOKEN_COUNTER,
EditorTabState,
ENABLE_TOKEN_COUNTER,
Expand All @@ -59,7 +63,6 @@ import {
RESET_WORKSPACE,
SEND_REPL_INPUT_TO_OUTPUT,
SET_FOLDER_MODE,
SET_TOKEN_COUNT,
SHIFT_EDITOR_TAB,
TOGGLE_EDITOR_AUTORUN,
TOGGLE_UPDATE_ENV,
Expand All @@ -83,6 +86,10 @@ import {
WorkspaceManagerState
} from './WorkspaceTypes';

const getWorkspaceLocation = (action: any): WorkspaceLocation => {
return action.payload ? action.payload.workspaceLocation : 'assessment';
};

/**
* Takes in a IWorkspaceManagerState and maps it to a new state. The
* pre-conditions are that
Expand All @@ -95,12 +102,7 @@ export const WorkspaceReducer: Reducer<WorkspaceManagerState> = (
state = defaultWorkspaceManager,
action: SourceActionType
) => {
const workspaceLocation: WorkspaceLocation = (action as any).payload
? (action as any).payload.workspaceLocation
: 'assessment';
let newOutput: InterpreterOutput[];
let lastOutput: InterpreterOutput;

const workspaceLocation = getWorkspaceLocation(action);
switch (workspaceLocation) {
case 'sourcecast':
const sourcecastState = SourcecastReducer(state.sourcecast, action);
Expand All @@ -124,138 +126,108 @@ export const WorkspaceReducer: Reducer<WorkspaceManagerState> = (
break;
}

switch (action.type) {
case SET_TOKEN_COUNT:
return {
...state,
[workspaceLocation]: {
...state[workspaceLocation],
tokenCount: action.payload.tokenCount
}
};
state = oldWorkspaceReducer(state, action);
state = newWorkspaceReducer(state, action);
return state;
};

case BROWSE_REPL_HISTORY_DOWN:
const newWorkspaceReducer = createReducer(defaultWorkspaceManager, builder => {
builder
.addCase(setTokenCount, (state, action) => {
const workspaceLocation = getWorkspaceLocation(action);
state[workspaceLocation].tokenCount = action.payload.tokenCount;
})
.addCase(browseReplHistoryDown, (state, action) => {
const workspaceLocation = getWorkspaceLocation(action);
if (state[workspaceLocation].replHistory.browseIndex === null) {
// Not yet started browsing history, nothing to do
return state;
} else if (state[workspaceLocation].replHistory.browseIndex !== 0) {
return;
}
if (state[workspaceLocation].replHistory.browseIndex !== 0) {
// Browsing history, and still have earlier records to show
const newIndex = state[workspaceLocation].replHistory.browseIndex! - 1;
const newReplValue = state[workspaceLocation].replHistory.records[newIndex];
return {
...state,
[workspaceLocation]: {
...state[workspaceLocation],
replValue: newReplValue,
replHistory: {
...state[workspaceLocation].replHistory,
browseIndex: newIndex
}
}
};
} else {
// Browsing history, no earlier records to show; return replValue to
// the last value when user started browsing
const newIndex = null;
const newReplValue = state[workspaceLocation].replHistory.originalValue;
const newRecords = state[workspaceLocation].replHistory.records.slice();
return {
...state,
[workspaceLocation]: {
...state[workspaceLocation],
replValue: newReplValue,
replHistory: {
browseIndex: newIndex,
records: newRecords,
originalValue: ''
}
}
};

state[workspaceLocation].replValue = newReplValue;
state[workspaceLocation].replHistory.browseIndex = newIndex;
return;
}
case BROWSE_REPL_HISTORY_UP:
// Browsing history, no earlier records to show; return replValue to
// the last value when user started browsing
const newIndex = null;
const newReplValue = state[workspaceLocation].replHistory.originalValue;
const newRecords = state[workspaceLocation].replHistory.records.slice();

state[workspaceLocation].replValue = newReplValue;
state[workspaceLocation].replHistory = {
browseIndex: newIndex,
records: newRecords,
originalValue: ''
};
})
.addCase(browseReplHistoryUp, (state, action) => {
const workspaceLocation = getWorkspaceLocation(action);
const lastRecords = state[workspaceLocation].replHistory.records;
const lastIndex = state[workspaceLocation].replHistory.browseIndex;
if (
lastRecords.length === 0 ||
(lastIndex !== null && lastRecords[lastIndex + 1] === undefined)
) {
// There is no more later history to show
return state;
} else if (lastIndex === null) {
return;
}
if (lastIndex === null) {
// Not yet started browsing, initialise the index & array
const newIndex = 0;
const newRecords = lastRecords.slice();
const originalValue = state[workspaceLocation].replValue;
const newReplValue = newRecords[newIndex];
return {
...state,
[workspaceLocation]: {
...state[workspaceLocation],
replValue: newReplValue,
replHistory: {
...state[workspaceLocation].replHistory,
browseIndex: newIndex,
records: newRecords,
originalValue
}
}
};
} else {
// Browsing history, and still have later history to show
const newIndex = lastIndex + 1;
const newReplValue = lastRecords[newIndex];
return {
...state,
[workspaceLocation]: {
...state[workspaceLocation],
replValue: newReplValue,
replHistory: {
...state[workspaceLocation].replHistory,
browseIndex: newIndex
}
}

state[workspaceLocation].replValue = newReplValue;
state[workspaceLocation].replHistory = {
browseIndex: newIndex,
records: newRecords,
originalValue
};
return;
}
case CHANGE_EXEC_TIME:
return {
...state,
[workspaceLocation]: {
...state[workspaceLocation],
execTime: action.payload.execTime
}
};
case CHANGE_STEP_LIMIT:
return {
...state,
[workspaceLocation]: {
...state[workspaceLocation],
stepLimit: action.payload.stepLimit
}
};
case CLEAR_REPL_INPUT:
return {
...state,
[workspaceLocation]: {
...state[workspaceLocation],
replValue: ''
}
};
case CLEAR_REPL_OUTPUT_LAST:
return {
...state,
[workspaceLocation]: {
...state[workspaceLocation],
output: state[workspaceLocation].output.slice(0, -1)
}
};
case CLEAR_REPL_OUTPUT:
return {
...state,
[workspaceLocation]: {
...state[workspaceLocation],
output: []
}
};
// Browsing history, and still have later history to show
const newIndex = lastIndex + 1;
const newReplValue = lastRecords[newIndex];
state[workspaceLocation].replValue = newReplValue;
state[workspaceLocation].replHistory.browseIndex = newIndex;
})
.addCase(changeExecTime, (state, action) => {
const workspaceLocation = getWorkspaceLocation(action);
state[workspaceLocation].execTime = action.payload.execTime;
})
.addCase(changeStepLimit, (state, action) => {
const workspaceLocation = getWorkspaceLocation(action);
state[workspaceLocation].stepLimit = action.payload.stepLimit;
})
.addCase(clearReplInput, (state, action) => {
const workspaceLocation = getWorkspaceLocation(action);
state[workspaceLocation].replValue = '';
})
.addCase(clearReplOutputLast, (state, action) => {
const workspaceLocation = getWorkspaceLocation(action);
state[workspaceLocation].output.pop();
})
.addCase(clearReplOutput, (state, action) => {
const workspaceLocation = getWorkspaceLocation(action);
state[workspaceLocation].output = [];
});
});

const oldWorkspaceReducer: Reducer<WorkspaceManagerState> = (
state = defaultWorkspaceManager,
action: SourceActionType
) => {
const workspaceLocation = getWorkspaceLocation(action);
let newOutput: InterpreterOutput[];
let lastOutput: InterpreterOutput;

switch (action.type) {
case END_CLEAR_CONTEXT:
return {
...state,
Expand Down
2 changes: 1 addition & 1 deletion src/commons/workspace/__tests__/WorkspaceActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ test('browseReplHistoryUp generates correct action object', () => {
});

test('changeExternalLibrary generates correct action object', () => {
const newExternal = 'new-external-test';
const newExternal = 'new-external-test' as ExternalLibraryName;
const action = changeExternalLibrary(newExternal, playgroundWorkspace);
expect(action).toEqual({
type: CHANGE_EXTERNAL_LIBRARY,
Expand Down
Loading