Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/snippets/components/edit.vue')
-rw-r--r--app/assets/javascripts/snippets/components/edit.vue81
1 files changed, 71 insertions, 10 deletions
diff --git a/app/assets/javascripts/snippets/components/edit.vue b/app/assets/javascripts/snippets/components/edit.vue
index ffb5e242973..9f43ac36df7 100644
--- a/app/assets/javascripts/snippets/components/edit.vue
+++ b/app/assets/javascripts/snippets/components/edit.vue
@@ -1,27 +1,28 @@
<script>
import { GlButton, GlLoadingIcon } from '@gitlab/ui';
+import eventHub from '~/blob/components/eventhub';
import { deprecatedCreateFlash as Flash } from '~/flash';
-import { __, sprintf } from '~/locale';
-import TitleField from '~/vue_shared/components/form/title.vue';
import { redirectTo, joinPaths } from '~/lib/utils/url_utility';
-import FormFooterActions from '~/vue_shared/components/form/form_footer_actions.vue';
+import { __, sprintf } from '~/locale';
import {
SNIPPET_MARK_EDIT_APP_START,
SNIPPET_MEASURE_BLOBS_CONTENT,
} from '~/performance/constants';
-import eventHub from '~/blob/components/eventhub';
import { performanceMarkAndMeasure } from '~/performance/utils';
+import FormFooterActions from '~/vue_shared/components/form/form_footer_actions.vue';
+import TitleField from '~/vue_shared/components/form/title.vue';
-import UpdateSnippetMutation from '../mutations/updateSnippet.mutation.graphql';
-import CreateSnippetMutation from '../mutations/createSnippet.mutation.graphql';
-import { getSnippetMixin } from '../mixins/snippets';
import { SNIPPET_CREATE_MUTATION_ERROR, SNIPPET_UPDATE_MUTATION_ERROR } from '../constants';
+import { getSnippetMixin } from '../mixins/snippets';
+import CreateSnippetMutation from '../mutations/createSnippet.mutation.graphql';
+import UpdateSnippetMutation from '../mutations/updateSnippet.mutation.graphql';
import { markBlobPerformance } from '../utils/blob';
+import { getErrorMessage } from '../utils/error';
import SnippetBlobActionsEdit from './snippet_blob_actions_edit.vue';
-import SnippetVisibilityEdit from './snippet_visibility_edit.vue';
import SnippetDescriptionEdit from './snippet_description_edit.vue';
+import SnippetVisibilityEdit from './snippet_visibility_edit.vue';
eventHub.$on(SNIPPET_MEASURE_BLOBS_CONTENT, markBlobPerformance);
@@ -32,6 +33,7 @@ export default {
SnippetBlobActionsEdit,
TitleField,
FormFooterActions,
+ CaptchaModal: () => import('~/captcha/captcha_modal.vue'),
GlButton,
GlLoadingIcon,
},
@@ -66,12 +68,25 @@ export default {
description: '',
visibilityLevel: this.selectedLevel,
},
+ captchaResponse: '',
+ needsCaptchaResponse: false,
+ captchaSiteKey: '',
+ spamLogId: '',
};
},
computed: {
hasBlobChanges() {
return this.actions.length > 0;
},
+ hasNoChanges() {
+ return (
+ this.actions.every(
+ (action) => !action.content && !action.filePath && !action.previousPath,
+ ) &&
+ !this.snippet.title &&
+ !this.snippet.description
+ );
+ },
hasValidBlobs() {
return this.actions.every((x) => x.content);
},
@@ -88,6 +103,8 @@ export default {
description: this.snippet.description,
visibilityLevel: this.snippet.visibilityLevel,
blobActions: this.actions,
+ ...(this.spamLogId && { spamLogId: this.spamLogId }),
+ ...(this.captchaResponse && { captchaResponse: this.captchaResponse }),
};
},
saveButtonLabel() {
@@ -116,7 +133,7 @@ export default {
onBeforeUnload(e = {}) {
const returnValue = __('Are you sure you want to lose unsaved changes?');
- if (!this.hasBlobChanges || this.isUpdating) return undefined;
+ if (!this.hasBlobChanges || this.hasNoChanges || this.isUpdating) return undefined;
Object.assign(e, { returnValue });
return returnValue;
@@ -159,6 +176,13 @@ export default {
.then(({ data }) => {
const baseObj = this.newSnippet ? data?.createSnippet : data?.updateSnippet;
+ if (baseObj.needsCaptchaResponse) {
+ // If we need a captcha response, start process for receiving captcha response.
+ // We will resubmit after the response is obtained.
+ this.requestCaptchaResponse(baseObj.captchaSiteKey, baseObj.spamLogId);
+ return;
+ }
+
const errors = baseObj?.errors;
if (errors.length) {
this.flashAPIFailure(errors[0]);
@@ -167,12 +191,44 @@ export default {
}
})
.catch((e) => {
- this.flashAPIFailure(e);
+ // eslint-disable-next-line no-console
+ console.error('[gitlab] unexpected error while updating snippet', e);
+
+ this.flashAPIFailure(getErrorMessage(e));
});
},
updateActions(actions) {
this.actions = actions;
},
+ /**
+ * Start process for getting captcha response from user
+ *
+ * @param captchaSiteKey Stored in data and used to display the captcha.
+ * @param spamLogId Stored in data and included when the form is re-submitted.
+ */
+ requestCaptchaResponse(captchaSiteKey, spamLogId) {
+ this.captchaSiteKey = captchaSiteKey;
+ this.spamLogId = spamLogId;
+ this.needsCaptchaResponse = true;
+ },
+ /**
+ * Handle the captcha response from the user
+ *
+ * @param captchaResponse The captchaResponse value emitted from the modal.
+ */
+ receivedCaptchaResponse(captchaResponse) {
+ this.needsCaptchaResponse = false;
+ this.captchaResponse = captchaResponse;
+
+ if (this.captchaResponse) {
+ // If the user solved the captcha resubmit the form.
+ this.handleFormSubmit();
+ } else {
+ // If the user didn't solve the captcha (e.g. they just closed the modal),
+ // finish the update and allow them to continue editing or manually resubmit the form.
+ this.isUpdating = false;
+ }
+ },
},
};
</script>
@@ -190,6 +246,11 @@ export default {
class="loading-animation prepend-top-20 gl-mb-6"
/>
<template v-else>
+ <captcha-modal
+ :captcha-site-key="captchaSiteKey"
+ :needs-captcha-response="needsCaptchaResponse"
+ @receivedCaptchaResponse="receivedCaptchaResponse"
+ />
<title-field
id="snippet-title"
v-model="snippet.title"