Skip to content

Removing autosave functionality (not in use) #1227

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jun 7, 2023
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
1 change: 0 additions & 1 deletion src/__mocks__/formDataStateMock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ export function getFormDataStateMock(customState?: Partial<IFormDataState>) {
'referencedGroup[2].inputField': 'Value from input field [2]',
},
lastSavedFormData: {},
savingId: '',
submittingId: '',
unsavedChanges: false,
saving: false,
Expand Down
1 change: 0 additions & 1 deletion src/__mocks__/uiConfigStateMock.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import type { IUiConfig } from 'src/types';

export const getUiConfigStateMock = (customStates?: Partial<IUiConfig>): IUiConfig => ({
autoSave: true,
focus: null,
tracks: {
hidden: [],
Expand Down
30 changes: 13 additions & 17 deletions src/features/formData/formDataSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ export const initialState: IFormDataState = {
unsavedChanges: false,
saving: false,
submittingId: '',
savingId: '',
error: null,
};

Expand Down Expand Up @@ -68,25 +67,12 @@ export const formDataSlice = () => {
submit: mkAction<ISubmitDataAction>({
takeEvery: submitFormSaga,
reducer: (state, action) => {
const { apiMode, componentId } = action.payload;
state.savingId = apiMode !== 'Complete' ? componentId : state.savingId;
state.submittingId = apiMode === 'Complete' ? componentId : state.submittingId;
},
}),
savingStarted: mkAction<void>({
reducer: (state) => {
state.saving = true;
},
}),
savingEnded: mkAction<{ model: IFormData }>({
reducer: (state, action) => {
state.saving = false;
state.lastSavedFormData = action.payload.model;
const { componentId } = action.payload;
state.submittingId = componentId;
},
}),
submitFulfilled: mkAction<void>({
reducer: (state) => {
state.savingId = '';
state.unsavedChanges = false;
},
}),
Expand All @@ -95,7 +81,17 @@ export const formDataSlice = () => {
const { error } = action.payload;
state.error = error;
state.submittingId = '';
state.savingId = '';
},
}),
savingStarted: mkAction<void>({
reducer: (state) => {
state.saving = true;
},
}),
savingEnded: mkAction<{ model: IFormData }>({
reducer: (state, action) => {
state.saving = false;
state.lastSavedFormData = action.payload.model;
},
}),
update: mkAction<IUpdateFormData>({
Expand Down
2 changes: 0 additions & 2 deletions src/features/formData/formDataTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ export interface IFormDataRejected {

export interface ISubmitDataAction {
url?: string;
apiMode?: string;
stopWithWarnings?: boolean;
componentId: string;
}

Expand Down
3 changes: 1 addition & 2 deletions src/features/formData/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@ export interface IFormDataState {
unsavedChanges: boolean;
saving: boolean;

// The component IDs which triggered submitting/saving last time
// The component IDs which triggered a submit (saving the form data in order to move to the next step)
submittingId: string;
savingId: string;

error: Error | null;
}
Expand Down
72 changes: 46 additions & 26 deletions src/features/formData/submit/submitFormDataSagas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,44 +25,43 @@ import {
} from 'src/utils/validation/validation';
import type { IApplicationMetadata } from 'src/features/applicationMetadata';
import type { IFormData } from 'src/features/formData';
import type { ISubmitDataAction, IUpdateFormDataFulfilled } from 'src/features/formData/formDataTypes';
import type { IUpdateFormDataFulfilled } from 'src/features/formData/formDataTypes';
import type { ILayoutState } from 'src/features/layout/formLayoutSlice';
import type { IRuntimeState, IRuntimeStore, IUiConfig, IValidationIssue } from 'src/types';
import type { IRuntimeState, IRuntimeStore, IValidationIssue } from 'src/types';

const LayoutSelector: (store: IRuntimeStore) => ILayoutState = (store: IRuntimeStore) => store.formLayout;
const UIConfigSelector: (store: IRuntimeStore) => IUiConfig = (store: IRuntimeStore) => store.formLayout.uiConfig;
const getApplicationMetaData = (store: IRuntimeState) => store.applicationMetadata?.applicationMetadata;

export function* submitFormSaga({
payload: { apiMode, stopWithWarnings },
}: PayloadAction<ISubmitDataAction>): SagaIterator {
/**
* Saga that submits the form data to the backend, and moves the process forward.
* @see autoSaveSaga
*/
export function* submitFormSaga(): SagaIterator {
try {
const state: IRuntimeState = yield select();
const { validationResult, componentSpecificValidations, emptyFieldsValidations } = runClientSideValidation(state);

validationResult.validations = mergeValidationObjects(
validationResult.validations,
componentSpecificValidations,
apiMode === 'Complete' ? emptyFieldsValidations : null,
emptyFieldsValidations,
);
const { validations } = validationResult;
if (!canFormBeSaved(validationResult, apiMode)) {
if (!canFormBeSaved(validationResult)) {
yield put(ValidationActions.updateValidations({ validations }));
return yield put(FormDataActions.submitRejected({ error: null }));
}

yield call(putFormData, {});
if (apiMode === 'Complete') {
yield call(submitComplete, state, stopWithWarnings);
}
yield call(submitComplete, state);
yield put(FormDataActions.submitFulfilled());
} catch (error) {
console.error(error);
yield put(FormDataActions.submitRejected({ error }));
}
}

function* submitComplete(state: IRuntimeState, stopWithWarnings: boolean | undefined) {
function* submitComplete(state: IRuntimeState) {
// run validations against the datamodel
const instanceId = state.instanceData.instance?.id;
const serverValidation: IValidationIssue[] | undefined = instanceId
Expand All @@ -78,8 +77,7 @@ function* submitComplete(state: IRuntimeState, stopWithWarnings: boolean | undef
);
yield put(ValidationActions.updateValidations({ validations: mappedValidations }));
const hasErrors = hasValidationsOfSeverity(mappedValidations, Severity.Error);
const hasWarnings = hasValidationsOfSeverity(mappedValidations, Severity.Warning);
if (hasErrors || (stopWithWarnings && hasWarnings)) {
if (hasErrors) {
// we have validation errors or warnings that should be shown, do not submit
return yield put(FormDataActions.submitRejected({ error: null }));
}
Expand Down Expand Up @@ -144,6 +142,17 @@ function* waitForSaving() {
yield put(FormDataActions.savingStarted());
}

/**
* This is the saving logic that is used for both autosaving and when the form is
* submitted at the end (moving the process forward).
*
* Strangely, this only performs the autosave logic for regular apps, but stateless apps have their own logic for this.
* However, when the form is submitted at the end, this is used for both regular and stateless apps.
*
* @see submitFormSaga
* @see autoSaveSaga
* @see postStatelessData
*/
export function* putFormData({ field, componentId }: SaveDataParams) {
const defaultDataElementGuid: string | undefined = yield select((state) =>
getCurrentTaskDataElementId(
Expand Down Expand Up @@ -233,6 +242,13 @@ function getModelToSave(state: IRuntimeState) {
);
}

/**
* Saves the form data to the backend, called from the auto-save saga. This calls the methods that actually perform
* the save operation, but this is NOT the saving logic that happens on _submit_ (when the form is submitted, and
* the process moves forward).
* @see autoSaveSaga
* @see submitFormSaga
*/
export function* saveFormDataSaga({
payload: { field, componentId, singleFieldValidation },
}: PayloadAction<IUpdateFormDataFulfilled>): SagaIterator {
Expand All @@ -242,7 +258,7 @@ export function* saveFormDataSaga({
const application = state.applicationMetadata.applicationMetadata;

if (isStatelessApp(application)) {
yield call(saveStatelessData, { field, componentId });
yield call(postStatelessData, { field, componentId });
} else {
// app with instance
yield call(putFormData, { field, componentId });
Expand Down Expand Up @@ -270,7 +286,13 @@ interface SaveDataParams {
componentId?: string;
}

export function* saveStatelessData({ field, componentId }: SaveDataParams) {
/**
* Innermost POST request that is called for stateless apps. This is only called during auto-save, and not when the
* form is submitted.
* @see saveFormDataSaga
* @see autoSaveSaga
*/
export function* postStatelessData({ field, componentId }: SaveDataParams) {
const state: IRuntimeState = yield select();
const model = getModelToSave(state);
const allowAnonymous = yield select(makeGetAllowAnonymousSelector());
Expand Down Expand Up @@ -319,24 +341,22 @@ export function* saveStatelessData({ field, componentId }: SaveDataParams) {
yield put(FormDataActions.savingEnded({ model: state.formData.formData }));
}

/**
* Auto-saves the form data when the user has made changes to the form. This is done very often.
* @see submitFormSaga
*/
export function* autoSaveSaga({
payload: { skipAutoSave, field, componentId, singleFieldValidation },
}: PayloadAction<IUpdateFormDataFulfilled>): SagaIterator {
if (skipAutoSave) {
return;
}

const uiConfig: IUiConfig = yield select(UIConfigSelector);
const applicationMetadata: IApplicationMetadata = yield select(getApplicationMetaData);

// undefined should default to auto save
const shouldAutoSave = uiConfig.autoSave !== false;

if (shouldAutoSave) {
if (isStatelessApp(applicationMetadata)) {
yield put(FormDataActions.saveLatest({ field, componentId, singleFieldValidation }));
} else {
yield put(FormDataActions.saveEvery({ field, componentId, singleFieldValidation }));
}
if (isStatelessApp(applicationMetadata)) {
yield put(FormDataActions.saveLatest({ field, componentId, singleFieldValidation }));
} else {
yield put(FormDataActions.saveEvery({ field, componentId, singleFieldValidation }));
}
}
6 changes: 0 additions & 6 deletions src/features/layout/fetch/fetchFormLayoutSagas.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ describe('fetchFormLayoutSagas', () => {
hiddenLayoutsExpressions: { ...hiddenExprPage1 },
}),
)
.put(FormLayoutActions.updateAutoSave({ autoSave: undefined }))
.put(
FormLayoutActions.updateCurrentView({
newView: 'page1',
Expand All @@ -120,7 +119,6 @@ describe('fetchFormLayoutSagas', () => {
hiddenLayoutsExpressions: { FormLayout: hiddenExprPage1['page1'] },
}),
)
.put(FormLayoutActions.updateAutoSave({ autoSave: undefined }))
.put(
FormLayoutActions.updateCurrentView({
newView: 'FormLayout',
Expand Down Expand Up @@ -169,7 +167,6 @@ describe('fetchFormLayoutSagas', () => {
},
}),
)
.put(FormLayoutActions.updateAutoSave({ autoSave: undefined }))
.put(
FormLayoutActions.updateCurrentView({
newView: 'page2',
Expand Down Expand Up @@ -201,7 +198,6 @@ describe('fetchFormLayoutSagas', () => {
},
}),
)
.put(FormLayoutActions.updateAutoSave({ autoSave: undefined }))
.put(
FormLayoutActions.updateCurrentView({
newView: 'page1',
Expand All @@ -227,7 +223,6 @@ describe('fetchFormLayoutSagas', () => {
hiddenLayoutsExpressions: { ...hiddenExprPage1 },
}),
)
.put(FormLayoutActions.updateAutoSave({ autoSave: undefined }))
.put(
FormLayoutActions.updateCurrentView({
newView: 'page1',
Expand All @@ -253,7 +248,6 @@ describe('fetchFormLayoutSagas', () => {
hiddenLayoutsExpressions: { ...hiddenExprPage1 },
}),
)
.put(FormLayoutActions.updateAutoSave({ autoSave: undefined }))
.put(
FormLayoutActions.updateCurrentView({
newView: 'page1',
Expand Down
4 changes: 0 additions & 4 deletions src/features/layout/fetch/fetchFormLayoutSagas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,11 @@ export function* fetchLayoutSaga(): SagaIterator {
const layouts: ILayouts = {};
const navigationConfig: any = {};
const hiddenLayoutsExpressions: ExprUnresolved<IHiddenLayoutsExpressions> = {};
let autoSave: boolean | undefined;
let firstLayoutKey: string;
if (layoutResponse.data?.layout) {
layouts.FormLayout = layoutResponse.data.layout;
hiddenLayoutsExpressions.FormLayout = layoutResponse.data.hidden;
firstLayoutKey = 'FormLayout';
autoSave = layoutResponse.data.autoSave;
} else {
const orderedLayoutKeys = Object.keys(layoutResponse).sort();

Expand All @@ -79,7 +77,6 @@ export function* fetchLayoutSaga(): SagaIterator {
layouts[key] = cleanLayout(layoutResponse[key].data.layout);
hiddenLayoutsExpressions[key] = layoutResponse[key].data.hidden;
navigationConfig[key] = layoutResponse[key].data.navigation;
autoSave = layoutResponse[key].data.autoSave;
});
}

Expand All @@ -102,7 +99,6 @@ export function* fetchLayoutSaga(): SagaIterator {
hiddenLayoutsExpressions,
}),
);
yield put(FormLayoutActions.updateAutoSave({ autoSave }));
yield put(
FormLayoutActions.updateCurrentView({
newView: firstLayoutKey,
Expand Down
7 changes: 0 additions & 7 deletions src/features/layout/formLayoutSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ export const initialState: ILayoutState = {
uiConfig: {
focus: null,
hiddenFields: [],
autoSave: null,
repeatingGroups: null,
fileUploadersWithTag: {},
receiptLayoutName: undefined,
Expand Down Expand Up @@ -162,12 +161,6 @@ export const formLayoutSlice = () => {
state.uiConfig.currentViewCacheKey = key;
},
}),
updateAutoSave: mkAction<LayoutTypes.IUpdateAutoSave>({
reducer: (state, action) => {
const { autoSave } = action.payload;
state.uiConfig.autoSave = autoSave;
},
}),
updateCurrentView: mkAction<LayoutTypes.IUpdateCurrentView>({
takeLatest: updateCurrentViewSaga,
}),
Expand Down
4 changes: 0 additions & 4 deletions src/features/layout/formLayoutTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,6 @@ export interface ISetCurrentViewCacheKey {
key: string | undefined;
}

export interface IUpdateAutoSave {
autoSave: boolean | undefined;
}

export interface IUpdateCurrentView {
newView: string;
returnToView?: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ export function* updateRepeatingGroupEditIndexSaga({
yield put(ValidationActions.updateValidations({ validations: newValidations }));
const rowValidations = filterValidationsByRow(resolvedNodes, combinedValidations, group, rowIndex);

if (canFormBeSaved({ validations: rowValidations, invalidDataTypes: false }, 'Complete')) {
if (canFormBeSaved({ validations: rowValidations, invalidDataTypes: false })) {
if (shouldAddRow) {
yield put(FormLayoutActions.repGroupAddRow({ groupId: group }));
}
Expand Down
11 changes: 4 additions & 7 deletions src/features/layout/update/updateFormLayoutSagas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,13 +136,10 @@ export function* updateCurrentViewSaga({
}),
);
} else if (
!canFormBeSaved(
{
validations: { [currentView]: validations[currentView] },
invalidDataTypes: false,
},
'Complete',
)
!canFormBeSaved({
validations: { [currentView]: validations[currentView] },
invalidDataTypes: false,
})
) {
yield put(
FormLayoutActions.updateCurrentViewRejected({
Expand Down
1 change: 0 additions & 1 deletion src/layout/Button/ButtonComponent.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ const render = (submittingId: string) => {
},
manipulateState: (state) => {
state.formData.submittingId = submittingId;
state.formLayout.uiConfig.autoSave = true;
},
});
};
Loading