fix: make crtl+s save to appropriate location (#45406)

* fix: crtl+s for multifile cert projects

* fix: remove unused code

* feat: add limit on save frequency
This commit is contained in:
Tom
2022-04-04 07:32:43 -05:00
committed by GitHub
parent f43de0969e
commit 3d242179b2
5 changed files with 36 additions and 4 deletions

View File

@ -533,6 +533,7 @@
"local-code-saved": "Saved! Your code was saved to your browser's local storage.",
"code-saved": "Your code was saved to the database. It will be here when you return.",
"code-save-error": "An error occurred trying to save your code.",
"code-save-less": "Slow Down! Your code was not saved. Try again in a few seconds.",
"challenge-save-too-big": "Sorry, you cannot save your code. Your code is {{user-size}} bytes. We allow a maximum of {{max-size}} bytes. Please make your code smaller and try again or request assistance on https://forum.freecodecamp.org",
"challenge-submit-too-big": "Sorry, you cannot submit your code. Your code is {{user-size}} bytes. We allow a maximum of {{max-size}} bytes. Please make your code smaller and try again or request assistance on https://forum.freecodecamp.org"
},

View File

@ -9,6 +9,7 @@ export enum FlashMessages {
ChallengeSubmitTooBig = 'flash.challenge-submit-too-big',
CodeSaved = 'flash.code-saved',
CodeSaveError = 'flash.code-save-error',
CodeSaveLess = 'flash.code-save-less',
CompleteProjectFirst = 'flash.complete-project-first',
DeleteTokenErr = 'flash.delete-token-err',
EmailValid = 'flash.email-valid',

View File

@ -13,11 +13,23 @@ import {
bodySizeFits,
MAX_BODY_SIZE
} from '../utils/challenge-request-helpers';
import { saveChallengeComplete } from './';
import { saveChallengeComplete, savedChallengesSelector } from './';
export function* saveChallengeSaga() {
const { id, challengeType } = yield select(challengeMetaSelector);
const { challengeFiles } = yield select(challengeDataSelector);
const savedChallenges = yield select(savedChallengesSelector);
const savedChallenge = savedChallenges.find(challenge => challenge.id === id);
// don't let users save more than once every 5 seconds
if (Date.now() - savedChallenge?.lastSavedDate < 5000) {
return yield put(
createFlashMessage({
type: 'danger',
message: FlashMessages.CodeSaveLess
})
);
}
// only allow saving of multiFileCertProject's
if (challengeType === challengeTypes.multiFileCertProject) {

View File

@ -20,7 +20,11 @@ import store from 'store';
import { Loader } from '../../../components/helpers';
import { Themes } from '../../../components/settings/theme';
import { userSelector, isDonationModalOpenSelector } from '../../../redux';
import {
userSelector,
saveChallenge,
isDonationModalOpenSelector
} from '../../../redux';
import {
ChallengeFiles,
Dimensions,
@ -31,8 +35,10 @@ import {
} from '../../../redux/prop-types';
import { editorToneOptions } from '../../../utils/tone/editor-config';
import { editorNotes } from '../../../utils/tone/editor-notes';
import { challengeTypes } from '../../../../utils/challenge-types';
import {
canFocusEditorSelector,
challengeMetaSelector,
consoleOutputSelector,
executeChallenge,
saveEditorContent,
@ -54,6 +60,7 @@ const MonacoEditor = Loadable(() => import('react-monaco-editor'));
interface EditorProps {
canFocus: boolean;
challengeFiles: ChallengeFiles;
challengeType: number;
containerRef: RefObject<HTMLElement>;
contents: string;
description: string;
@ -70,6 +77,7 @@ interface EditorProps {
isResetting: boolean;
output: string[];
resizeProps: ResizeProps;
saveChallenge: () => void;
saveEditorContent: () => void;
setEditorFocusability: (isFocusable: boolean) => void;
submitChallenge: () => void;
@ -105,6 +113,7 @@ interface EditorProperties {
const mapStateToProps = createSelector(
canFocusEditorSelector,
challengeMetaSelector,
consoleOutputSelector,
isDonationModalOpenSelector,
isProjectPreviewModalOpenSelector,
@ -113,6 +122,7 @@ const mapStateToProps = createSelector(
challengeTestsSelector,
(
canFocus: boolean,
{ challengeType }: { challengeType: number },
output: string[],
open,
previewOpen: boolean,
@ -121,6 +131,7 @@ const mapStateToProps = createSelector(
tests: [{ text: string; testString: string }]
) => ({
canFocus: open ? false : canFocus,
challengeType,
previewOpen,
isResetting,
output,
@ -133,6 +144,7 @@ const mapStateToProps = createSelector(
const mapDispatchToProps = {
executeChallenge,
saveChallenge,
saveEditorContent,
setEditorFocusability,
updateFile,
@ -396,9 +408,14 @@ const Editor = (props: EditorProps): JSX.Element => {
});
editor.addAction({
id: 'save-editor-content',
label: 'Save editor content to localStorage',
label: 'Save editor content',
keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.KEY_S],
run: props.saveEditorContent
run:
props.challengeType === challengeTypes.multiFileCertProject
? // save to database
props.saveChallenge
: // save to local storage
props.saveEditorContent
});
editor.addAction({
id: 'toggle-accessibility',

View File

@ -24,6 +24,7 @@ const toneUrls = {
[FlashMessages.ChallengeSubmitTooBig]: TRY_AGAIN,
[FlashMessages.CodeSaved]: CHAL_COMP,
[FlashMessages.CodeSaveError]: TRY_AGAIN,
[FlashMessages.CodeSaveLess]: TRY_AGAIN,
[FlashMessages.CompleteProjectFirst]: TRY_AGAIN,
[FlashMessages.DeleteTokenErr]: TRY_AGAIN,
[FlashMessages.EmailValid]: CHAL_COMP,