diff --git a/.rubocop.yml b/.rubocop.yml index dac452cb484..dd43221d20e 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -994,7 +994,7 @@ Gemspec/AvoidExecutingGit: Lint/BinaryOperatorWithIdenticalOperands: Exclude: - - '{,ee/,qa/}spec/**/*_{spec,shared_examples,shared_context}.rb' + - '{,ee/,qa/,jh/}spec/**/*_{spec,shared_examples,shared_context}.rb' Cop/SidekiqRedisCall: Enabled: true diff --git a/Gemfile.lock b/Gemfile.lock index 3cbaf38ed71..69a3a0356cf 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -67,6 +67,7 @@ PATH remote: gems/gitlab-safe_request_store specs: gitlab-safe_request_store (0.1.0) + rack (~> 2.2.8) request_store PATH diff --git a/app/assets/javascripts/dropzone_input.js b/app/assets/javascripts/dropzone_input.js index 9ee4f7cf4aa..17744e2c6ab 100644 --- a/app/assets/javascripts/dropzone_input.js +++ b/app/assets/javascripts/dropzone_input.js @@ -46,7 +46,6 @@ export default function dropzoneInput(form, config = { parallelUploads: 2 }) { let hasPlainText; formTextarea.wrap('
'); - formTextarea.on('paste', (event) => handlePaste(event)); // Add dropzone area to the form. const $mdArea = formTextarea.closest('.md-area'); @@ -60,6 +59,8 @@ export default function dropzoneInput(form, config = { parallelUploads: 2 }) { return null; } + formTextarea.on('paste', (event) => handlePaste(event)); + const dropzone = $formDropzone.dropzone({ url: uploadsPath, dictDefaultMessage: '', diff --git a/app/assets/javascripts/organizations/new/components/app.vue b/app/assets/javascripts/organizations/new/components/app.vue index ee50afd3613..3a2b786dbae 100644 --- a/app/assets/javascripts/organizations/new/components/app.vue +++ b/app/assets/javascripts/organizations/new/components/app.vue @@ -42,7 +42,12 @@ export default { } = await this.$apollo.mutate({ mutation: organizationCreateMutation, variables: { - input: { name: formValues.name, path: formValues.path, avatar: formValues.avatar }, + input: { + name: formValues.name, + path: formValues.path, + description: formValues.description, + avatar: formValues.avatar, + }, }, context: { hasUpload: formValues.avatar instanceof File, diff --git a/app/assets/javascripts/organizations/new/index.js b/app/assets/javascripts/organizations/new/index.js index 9c7e5344800..563e366b2c6 100644 --- a/app/assets/javascripts/organizations/new/index.js +++ b/app/assets/javascripts/organizations/new/index.js @@ -13,7 +13,9 @@ export const initOrganizationsNew = () => { const { dataset: { appData }, } = el; - const { organizationsPath, rootUrl } = convertObjectPropsToCamelCase(JSON.parse(appData)); + const { organizationsPath, rootUrl, previewMarkdownPath } = convertObjectPropsToCamelCase( + JSON.parse(appData), + ); const apolloProvider = new VueApollo({ defaultClient: createDefaultClient(), @@ -26,6 +28,7 @@ export const initOrganizationsNew = () => { provide: { organizationsPath, rootUrl, + previewMarkdownPath, }, render(createElement) { return createElement(App); diff --git a/app/assets/javascripts/organizations/settings/general/components/organization_settings.vue b/app/assets/javascripts/organizations/settings/general/components/organization_settings.vue index 283a652f90e..1cea2ceeb90 100644 --- a/app/assets/javascripts/organizations/settings/general/components/organization_settings.vue +++ b/app/assets/javascripts/organizations/settings/general/components/organization_settings.vue @@ -6,6 +6,7 @@ import NewEditForm from '~/organizations/shared/components/new_edit_form.vue'; import { FORM_FIELD_NAME, FORM_FIELD_ID, + FORM_FIELD_DESCRIPTION, FORM_FIELD_AVATAR, } from '~/organizations/shared/constants'; import SettingsBlock from '~/vue_shared/components/settings/settings_block.vue'; @@ -29,7 +30,7 @@ export default { ), successMessage: s__('Organization|Organization was successfully updated.'), }, - fieldsToRender: [FORM_FIELD_NAME, FORM_FIELD_ID, FORM_FIELD_AVATAR], + fieldsToRender: [FORM_FIELD_NAME, FORM_FIELD_ID, FORM_FIELD_DESCRIPTION, FORM_FIELD_AVATAR], data() { return { loading: false, @@ -66,6 +67,7 @@ export default { input: { id: convertToGraphQLId(TYPE_ORGANIZATION, this.organization.id), name: formValues.name, + description: formValues.description, ...this.avatarInput(formValues), }, }, diff --git a/app/assets/javascripts/organizations/settings/general/index.js b/app/assets/javascripts/organizations/settings/general/index.js index 138606a0aab..3ac1243ff0f 100644 --- a/app/assets/javascripts/organizations/settings/general/index.js +++ b/app/assets/javascripts/organizations/settings/general/index.js @@ -13,9 +13,12 @@ export const initOrganizationsSettingsGeneral = () => { const { dataset: { appData }, } = el; - const { organization, organizationsPath, rootUrl } = convertObjectPropsToCamelCase( - JSON.parse(appData), - ); + const { + organization, + organizationsPath, + rootUrl, + previewMarkdownPath, + } = convertObjectPropsToCamelCase(JSON.parse(appData)); const apolloProvider = new VueApollo({ defaultClient: createDefaultClient(), @@ -29,6 +32,7 @@ export const initOrganizationsSettingsGeneral = () => { organization, organizationsPath, rootUrl, + previewMarkdownPath, }, render(createElement) { return createElement(App); diff --git a/app/assets/javascripts/organizations/shared/components/new_edit_form.vue b/app/assets/javascripts/organizations/shared/components/new_edit_form.vue index 3567fa490ea..49519369e9a 100644 --- a/app/assets/javascripts/organizations/shared/components/new_edit_form.vue +++ b/app/assets/javascripts/organizations/shared/components/new_edit_form.vue @@ -4,10 +4,13 @@ import { formValidators } from '@gitlab/ui/dist/utils'; import { s__, __ } from '~/locale'; import { slugify } from '~/lib/utils/text_utility'; import AvatarUploadDropzone from '~/vue_shared/components/upload_dropzone/avatar_upload_dropzone.vue'; +import MarkdownField from '~/vue_shared/components/markdown/field.vue'; +import { helpPagePath } from '~/helpers/help_page_helper'; import { FORM_FIELD_NAME, FORM_FIELD_ID, FORM_FIELD_PATH, + FORM_FIELD_DESCRIPTION, FORM_FIELD_AVATAR, FORM_FIELD_PATH_VALIDATORS, } from '../constants'; @@ -21,12 +24,27 @@ export default { GlButton, OrganizationUrlField, AvatarUploadDropzone, + MarkdownField, }, i18n: { cancel: __('Cancel'), }, formId: 'new-organization-form', - inject: ['organizationsPath'], + markdownDocsPath: helpPagePath('user/organization/index', { + anchor: 'organization-description-supported-markdown', + }), + restrictedToolBarItems: [ + 'code', + 'quote', + 'bullet-list', + 'numbered-list', + 'task-list', + 'collapsible-section', + 'table', + 'attach-file', + 'full-screen', + ], + inject: ['organizationsPath', 'previewMarkdownPath'], props: { loading: { type: Boolean, @@ -39,6 +57,7 @@ export default { return { [FORM_FIELD_NAME]: '', [FORM_FIELD_PATH]: '', + [FORM_FIELD_DESCRIPTION]: '', [FORM_FIELD_AVATAR]: null, }; }, @@ -47,7 +66,7 @@ export default { type: Array, required: false, default() { - return [FORM_FIELD_NAME, FORM_FIELD_PATH, FORM_FIELD_AVATAR]; + return [FORM_FIELD_NAME, FORM_FIELD_PATH, FORM_FIELD_DESCRIPTION, FORM_FIELD_AVATAR]; }, }, submitButtonText: { @@ -102,6 +121,12 @@ export default { class: 'gl-w-full', }, }, + [FORM_FIELD_DESCRIPTION]: { + label: s__('Organization|Organization description (optional)'), + groupAttrs: { + class: 'gl-w-full common-note-form', + }, + }, [FORM_FIELD_AVATAR]: { label: s__('Organization|Organization avatar'), groupAttrs: { @@ -137,6 +162,7 @@ export default { formFieldsInputEvent(event); this.hasPathBeenManuallySet = true; }, + helpPagePath, }, }; @@ -159,6 +185,28 @@ export default { @blur="blur" /> +