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
path: root/app
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-03-03 12:10:53 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-03-03 12:10:53 +0300
commit74780f24f2005d24a0e0a8fa1b3ae5391ae2928f (patch)
tree888505246a85ff9e97042b43b18450730586596e /app
parentccbe90951fb75b3527eaaad404e6abb6ed09ca8c (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue304
-rw-r--r--app/assets/javascripts/pages/projects/forks/new/index.js61
-rw-r--r--app/assets/javascripts/repository/components/breadcrumbs.vue53
-rw-r--r--app/assets/javascripts/repository/components/upload_blob_modal.vue218
-rw-r--r--app/assets/javascripts/repository/index.js15
-rw-r--r--app/assets/stylesheets/page_bundles/boards.scss4
-rw-r--r--app/controllers/projects/forks_controller.rb4
-rw-r--r--app/graphql/types/todo_action_enum.rb16
-rw-r--r--app/helpers/tree_helper.rb2
-rw-r--r--app/views/dashboard/projects/_projects.html.haml2
-rw-r--r--app/views/projects/_files.html.haml1
-rw-r--r--app/views/projects/forks/new.html.haml24
-rw-r--r--app/views/projects/runners/_runner.html.haml2
13 files changed, 399 insertions, 307 deletions
diff --git a/app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue b/app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue
new file mode 100644
index 00000000000..a59a8afa4de
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/forks/new/components/fork_form.vue
@@ -0,0 +1,304 @@
+<script>
+import {
+ GlIcon,
+ GlLink,
+ GlForm,
+ GlFormInputGroup,
+ GlInputGroupText,
+ GlFormInput,
+ GlFormGroup,
+ GlFormTextarea,
+ GlButton,
+ GlFormRadio,
+ GlFormRadioGroup,
+ GlFormSelect,
+} from '@gitlab/ui';
+import { buildApiUrl } from '~/api/api_utils';
+import createFlash from '~/flash';
+import axios from '~/lib/utils/axios_utils';
+import csrf from '~/lib/utils/csrf';
+import { redirectTo } from '~/lib/utils/url_utility';
+import { s__ } from '~/locale';
+
+const PRIVATE_VISIBILITY = 'private';
+const INTERNAL_VISIBILITY = 'internal';
+const PUBLIC_VISIBILITY = 'public';
+
+const ALLOWED_VISIBILITY = {
+ private: [PRIVATE_VISIBILITY],
+ internal: [INTERNAL_VISIBILITY, PRIVATE_VISIBILITY],
+ public: [INTERNAL_VISIBILITY, PRIVATE_VISIBILITY, PUBLIC_VISIBILITY],
+};
+
+export default {
+ components: {
+ GlForm,
+ GlIcon,
+ GlLink,
+ GlButton,
+ GlFormInputGroup,
+ GlInputGroupText,
+ GlFormInput,
+ GlFormTextarea,
+ GlFormGroup,
+ GlFormRadio,
+ GlFormRadioGroup,
+ GlFormSelect,
+ },
+ props: {
+ endpoint: {
+ type: String,
+ required: true,
+ },
+ newGroupPath: {
+ type: String,
+ required: true,
+ },
+ projectFullPath: {
+ type: String,
+ required: true,
+ },
+ visibilityHelpPath: {
+ type: String,
+ required: true,
+ },
+ projectId: {
+ type: String,
+ required: true,
+ },
+ projectName: {
+ type: String,
+ required: true,
+ },
+ projectPath: {
+ type: String,
+ required: true,
+ },
+ projectDescription: {
+ type: String,
+ required: true,
+ },
+ projectVisibility: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ isSaving: false,
+ namespaces: [],
+ selectedNamespace: {},
+ fork: {
+ name: this.projectName,
+ slug: this.projectPath,
+ description: this.projectDescription,
+ visibility: this.projectVisibility,
+ },
+ };
+ },
+ computed: {
+ projectUrl() {
+ return `${gon.gitlab_url}/`;
+ },
+ projectAllowedVisibility() {
+ return ALLOWED_VISIBILITY[this.projectVisibility];
+ },
+ namespaceAllowedVisibility() {
+ return (
+ ALLOWED_VISIBILITY[this.selectedNamespace.visibility] ||
+ ALLOWED_VISIBILITY[PUBLIC_VISIBILITY]
+ );
+ },
+ visibilityLevels() {
+ return [
+ {
+ text: s__('ForkProject|Private'),
+ value: PRIVATE_VISIBILITY,
+ icon: 'lock',
+ help: s__('ForkProject|The project can be accessed without any authentication.'),
+ disabled: this.isVisibilityLevelDisabled(PRIVATE_VISIBILITY),
+ },
+ {
+ text: s__('ForkProject|Internal'),
+ value: INTERNAL_VISIBILITY,
+ icon: 'shield',
+ help: s__('ForkProject|The project can be accessed by any logged in user.'),
+ disabled: this.isVisibilityLevelDisabled(INTERNAL_VISIBILITY),
+ },
+ {
+ text: s__('ForkProject|Public'),
+ value: PUBLIC_VISIBILITY,
+ icon: 'earth',
+ help: s__(
+ 'ForkProject|Project access must be granted explicitly to each user. If this project is part of a group, access will be granted to members of the group.',
+ ),
+ disabled: this.isVisibilityLevelDisabled(PUBLIC_VISIBILITY),
+ },
+ ];
+ },
+ },
+ watch: {
+ selectedNamespace(newVal) {
+ const { visibility } = newVal;
+
+ if (this.projectAllowedVisibility.includes(visibility)) {
+ this.fork.visibility = visibility;
+ }
+ },
+ },
+ mounted() {
+ this.fetchNamespaces();
+ },
+ methods: {
+ async fetchNamespaces() {
+ const { data } = await axios.get(this.endpoint);
+ this.namespaces = data.namespaces;
+ },
+ isVisibilityLevelDisabled(visibilityLevel) {
+ return !(
+ this.projectAllowedVisibility.includes(visibilityLevel) &&
+ this.namespaceAllowedVisibility.includes(visibilityLevel)
+ );
+ },
+ async onSubmit() {
+ this.isSaving = true;
+
+ const { projectId } = this;
+ const { name, slug, description, visibility } = this.fork;
+ const { id: namespaceId } = this.selectedNamespace;
+
+ const postParams = {
+ id: projectId,
+ name,
+ namespace_id: namespaceId,
+ path: slug,
+ description,
+ visibility,
+ };
+
+ const forkProjectPath = `/api/:version/projects/:id/fork`;
+ const url = buildApiUrl(forkProjectPath).replace(':id', encodeURIComponent(this.projectId));
+
+ try {
+ const { data } = await axios.post(url, postParams);
+ redirectTo(data.web_url);
+ return;
+ } catch (error) {
+ createFlash({ message: error });
+ }
+ },
+ },
+ csrf,
+};
+</script>
+
+<template>
+ <gl-form method="POST" @submit.prevent="onSubmit">
+ <input type="hidden" name="authenticity_token" :value="$options.csrf.token" />
+
+ <gl-form-group label="Project name" label-for="fork-name">
+ <gl-form-input id="fork-name" v-model="fork.name" data-testid="fork-name-input" required />
+ </gl-form-group>
+
+ <div class="gl-display-flex">
+ <div class="gl-w-half">
+ <gl-form-group label="Project URL" label-for="fork-url" class="gl-pr-2">
+ <gl-form-input-group>
+ <template #prepend>
+ <gl-input-group-text>
+ {{ projectUrl }}
+ </gl-input-group-text>
+ </template>
+ <gl-form-select
+ id="fork-url"
+ v-model="selectedNamespace"
+ data-testid="fork-url-input"
+ required
+ >
+ <template slot="first">
+ <option :value="null" disabled>{{ s__('ForkProject|Select a namespace') }}</option>
+ </template>
+ <option v-for="namespace in namespaces" :key="namespace.id" :value="namespace">
+ {{ namespace.name }}
+ </option>
+ </gl-form-select>
+ </gl-form-input-group>
+ </gl-form-group>
+ </div>
+ <div class="gl-w-half">
+ <gl-form-group label="Project slug" label-for="fork-slug" class="gl-pl-2">
+ <gl-form-input
+ id="fork-slug"
+ v-model="fork.slug"
+ data-testid="fork-slug-input"
+ required
+ />
+ </gl-form-group>
+ </div>
+ </div>
+
+ <p class="gl-mt-n5 gl-text-gray-500">
+ {{ s__('ForkProject|Want to house several dependent projects under the same namespace?') }}
+ <gl-link :href="newGroupPath" target="_blank">
+ {{ s__('ForkProject|Create a group') }}
+ </gl-link>
+ </p>
+
+ <gl-form-group label="Project description (optional)" label-for="fork-description">
+ <gl-form-textarea
+ id="fork-description"
+ v-model="fork.description"
+ data-testid="fork-description-textarea"
+ />
+ </gl-form-group>
+
+ <gl-form-group>
+ <label>
+ {{ s__('ForkProject|Visibility level') }}
+ <gl-link :href="visibilityHelpPath" target="_blank">
+ <gl-icon name="question-o" />
+ </gl-link>
+ </label>
+ <gl-form-radio-group
+ v-model="fork.visibility"
+ data-testid="fork-visibility-radio-group"
+ required
+ >
+ <gl-form-radio
+ v-for="{ text, value, icon, help, disabled } in visibilityLevels"
+ :key="value"
+ :value="value"
+ :disabled="disabled"
+ :data-testid="`radio-${value}`"
+ >
+ <div>
+ <gl-icon :name="icon" />
+ <span>{{ text }}</span>
+ </div>
+ <template #help>{{ help }}</template>
+ </gl-form-radio>
+ </gl-form-radio-group>
+ </gl-form-group>
+
+ <div class="gl-display-flex gl-justify-content-space-between gl-mt-8">
+ <gl-button
+ type="submit"
+ category="primary"
+ variant="confirm"
+ data-testid="submit-button"
+ :loading="isSaving"
+ >
+ {{ s__('ForkProject|Fork project') }}
+ </gl-button>
+ <gl-button
+ type="reset"
+ class="gl-mr-3"
+ data-testid="cancel-button"
+ :disabled="isSaving"
+ :href="projectFullPath"
+ >
+ {{ s__('ForkProject|Cancel') }}
+ </gl-button>
+ </div>
+ </gl-form>
+</template>
diff --git a/app/assets/javascripts/pages/projects/forks/new/index.js b/app/assets/javascripts/pages/projects/forks/new/index.js
index 26353aefe82..420639eefb7 100644
--- a/app/assets/javascripts/pages/projects/forks/new/index.js
+++ b/app/assets/javascripts/pages/projects/forks/new/index.js
@@ -1,16 +1,53 @@
import Vue from 'vue';
+import ForkForm from './components/fork_form.vue';
import ForkGroupsList from './components/fork_groups_list.vue';
const mountElement = document.getElementById('fork-groups-mount-element');
-const { endpoint } = mountElement.dataset;
-// eslint-disable-next-line no-new
-new Vue({
- el: mountElement,
- render(h) {
- return h(ForkGroupsList, {
- props: {
- endpoint,
- },
- });
- },
-});
+
+if (gon.features.forkProjectForm) {
+ const {
+ endpoint,
+ newGroupPath,
+ projectFullPath,
+ visibilityHelpPath,
+ projectId,
+ projectName,
+ projectPath,
+ projectDescription,
+ projectVisibility,
+ } = mountElement.dataset;
+
+ // eslint-disable-next-line no-new
+ new Vue({
+ el: mountElement,
+ render(h) {
+ return h(ForkForm, {
+ props: {
+ endpoint,
+ newGroupPath,
+ projectFullPath,
+ visibilityHelpPath,
+ projectId,
+ projectName,
+ projectPath,
+ projectDescription,
+ projectVisibility,
+ },
+ });
+ },
+ });
+} else {
+ const { endpoint } = mountElement.dataset;
+
+ // eslint-disable-next-line no-new
+ new Vue({
+ el: mountElement,
+ render(h) {
+ return h(ForkGroupsList, {
+ props: {
+ endpoint,
+ },
+ });
+ },
+ });
+}
diff --git a/app/assets/javascripts/repository/components/breadcrumbs.vue b/app/assets/javascripts/repository/components/breadcrumbs.vue
index 70167bde188..28d7dec85f4 100644
--- a/app/assets/javascripts/repository/components/breadcrumbs.vue
+++ b/app/assets/javascripts/repository/components/breadcrumbs.vue
@@ -5,7 +5,6 @@ import {
GlDropdownSectionHeader,
GlDropdownItem,
GlIcon,
- GlModalDirective,
} from '@gitlab/ui';
import permissionsQuery from 'shared_queries/repository/permissions.query.graphql';
import { joinPaths, escapeFileUrl } from '~/lib/utils/url_utility';
@@ -13,15 +12,12 @@ import { __ } from '../../locale';
import getRefMixin from '../mixins/get_ref';
import projectPathQuery from '../queries/project_path.query.graphql';
import projectShortPathQuery from '../queries/project_short_path.query.graphql';
-import UploadBlobModal from './upload_blob_modal.vue';
const ROW_TYPES = {
header: 'header',
divider: 'divider',
};
-const UPLOAD_BLOB_MODAL_ID = 'modal-upload-blob';
-
export default {
components: {
GlDropdown,
@@ -29,7 +25,6 @@ export default {
GlDropdownSectionHeader,
GlDropdownItem,
GlIcon,
- UploadBlobModal,
},
apollo: {
projectShortPath: {
@@ -51,9 +46,6 @@ export default {
},
},
},
- directives: {
- GlModal: GlModalDirective,
- },
mixins: [getRefMixin],
props: {
currentPath: {
@@ -71,21 +63,6 @@ export default {
required: false,
default: false,
},
- canPushCode: {
- type: Boolean,
- required: false,
- default: false,
- },
- selectedBranch: {
- type: String,
- required: false,
- default: '',
- },
- origionalBranch: {
- type: String,
- required: false,
- default: '',
- },
newBranchPath: {
type: String,
required: false,
@@ -116,13 +93,7 @@ export default {
required: false,
default: null,
},
- uploadPath: {
- type: String,
- required: false,
- default: '',
- },
},
- uploadBlobModalId: UPLOAD_BLOB_MODAL_ID,
data() {
return {
projectShortPath: '',
@@ -155,10 +126,7 @@ export default {
);
},
canCreateMrFromFork() {
- return this.userPermissions?.forkProject && this.userPermissions?.createMergeRequestIn;
- },
- showUploadModal() {
- return this.canEditTree && !this.$apollo.queries.userPermissions.loading;
+ return this.userPermissions.forkProject && this.userPermissions.createMergeRequestIn;
},
dropdownItems() {
const items = [];
@@ -181,9 +149,10 @@ export default {
{
attrs: {
href: '#modal-upload-blob',
+ 'data-target': '#modal-upload-blob',
+ 'data-toggle': 'modal',
},
text: __('Upload file'),
- modalId: UPLOAD_BLOB_MODAL_ID,
},
{
attrs: {
@@ -284,26 +253,12 @@ export default {
<gl-icon name="chevron-down" :size="16" class="float-left" />
</template>
<template v-for="(item, i) in dropdownItems">
- <component
- :is="getComponent(item.type)"
- :key="i"
- v-bind="item.attrs"
- v-gl-modal="item.modalId || null"
- >
+ <component :is="getComponent(item.type)" :key="i" v-bind="item.attrs">
{{ item.text }}
</component>
</template>
</gl-dropdown>
</li>
</ol>
- <upload-blob-modal
- v-if="showUploadModal"
- :modal-id="$options.uploadBlobModalId"
- :commit-message="__('Upload New File')"
- :target-branch="selectedBranch"
- :origional-branch="origionalBranch"
- :can-push-code="canPushCode"
- :path="uploadPath"
- />
</nav>
</template>
diff --git a/app/assets/javascripts/repository/components/upload_blob_modal.vue b/app/assets/javascripts/repository/components/upload_blob_modal.vue
deleted file mode 100644
index 4cdfc5e947a..00000000000
--- a/app/assets/javascripts/repository/components/upload_blob_modal.vue
+++ /dev/null
@@ -1,218 +0,0 @@
-<script>
-import {
- GlModal,
- GlForm,
- GlFormGroup,
- GlFormInput,
- GlFormTextarea,
- GlToggle,
- GlButton,
- GlAlert,
-} from '@gitlab/ui';
-import createFlash from '~/flash';
-import axios from '~/lib/utils/axios_utils';
-import { ContentTypeMultipartFormData } from '~/lib/utils/headers';
-import { numberToHumanSize } from '~/lib/utils/number_utils';
-import { visitUrl, joinPaths } from '~/lib/utils/url_utility';
-import { __ } from '~/locale';
-import UploadDropzone from '~/vue_shared/components/upload_dropzone/upload_dropzone.vue';
-
-const PRIMARY_OPTIONS_TEXT = __('Upload file');
-const SECONDARY_OPTIONS_TEXT = __('Cancel');
-const MODAL_TITLE = __('Upload New File');
-const COMMIT_LABEL = __('Commit message');
-const TARGET_BRANCH_LABEL = __('Target branch');
-const TOGGLE_CREATE_MR_LABEL = __('Start a new merge request with these changes');
-const REMOVE_FILE_TEXT = __('Remove file');
-const NEW_BRANCH_IN_FORK = __(
- 'A new branch will be created in your fork and a new merge request will be started.',
-);
-const ERROR_MESSAGE = __('Error uploading file. Please try again.');
-
-export default {
- components: {
- GlModal,
- GlForm,
- GlFormGroup,
- GlFormInput,
- GlFormTextarea,
- GlToggle,
- GlButton,
- UploadDropzone,
- GlAlert,
- },
- i18n: {
- MODAL_TITLE,
- COMMIT_LABEL,
- TARGET_BRANCH_LABEL,
- TOGGLE_CREATE_MR_LABEL,
- REMOVE_FILE_TEXT,
- NEW_BRANCH_IN_FORK,
- },
- props: {
- modalId: {
- type: String,
- required: true,
- },
- commitMessage: {
- type: String,
- required: true,
- },
- targetBranch: {
- type: String,
- required: true,
- },
- origionalBranch: {
- type: String,
- required: true,
- },
- canPushCode: {
- type: Boolean,
- required: true,
- },
- path: {
- type: String,
- required: true,
- },
- },
- data() {
- return {
- commit: this.commitMessage,
- target: this.targetBranch,
- createNewMr: true,
- file: null,
- filePreviewURL: null,
- fileBinary: null,
- loading: false,
- };
- },
- computed: {
- primaryOptions() {
- return {
- text: PRIMARY_OPTIONS_TEXT,
- attributes: [
- {
- variant: 'success',
- loading: this.loading,
- disabled: !this.formCompleted || this.loading,
- },
- ],
- };
- },
- cancelOptions() {
- return {
- text: SECONDARY_OPTIONS_TEXT,
- attributes: [
- {
- disabled: this.loading,
- },
- ],
- };
- },
- formattedFileSize() {
- return numberToHumanSize(this.file.size);
- },
- showCreateNewMrToggle() {
- return this.canPushCode && this.target !== this.origionalBranch;
- },
- formCompleted() {
- return this.file && this.commit && this.target;
- },
- },
- methods: {
- setFile(file) {
- this.file = file;
-
- const fileUurlReader = new FileReader();
-
- fileUurlReader.readAsDataURL(this.file);
-
- fileUurlReader.onload = (e) => {
- this.filePreviewURL = e.target?.result;
- };
- },
- removeFile() {
- this.file = null;
- this.filePreviewURL = null;
- },
- uploadFile() {
- this.loading = true;
-
- const {
- $route: {
- params: { path },
- },
- } = this;
- const uploadPath = joinPaths(this.path, path);
-
- const formData = new FormData();
- formData.append('branch_name', this.target);
- formData.append('create_merge_request', this.createNewMr);
- formData.append('commit_message', this.commit);
- formData.append('file', this.file);
-
- return axios
- .post(uploadPath, formData, {
- headers: {
- ...ContentTypeMultipartFormData,
- },
- })
- .then((response) => {
- visitUrl(response.data.filePath);
- })
- .catch(() => {
- this.loading = false;
- createFlash(ERROR_MESSAGE);
- });
- },
- },
-};
-</script>
-<template>
- <gl-form>
- <gl-modal
- :modal-id="modalId"
- :title="$options.i18n.MODAL_TITLE"
- :action-primary="primaryOptions"
- :action-cancel="cancelOptions"
- @primary.prevent="uploadFile"
- >
- <upload-dropzone class="gl-h-200! gl-mb-4" single-file-selection @change="setFile">
- <div
- v-if="file"
- class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-3"
- >
- <img v-if="filePreviewURL" :src="filePreviewURL" class="gl-h-11" />
- <div>{{ formattedFileSize }}</div>
- <div>{{ file.name }}</div>
- <gl-button
- category="tertiary"
- variant="confirm"
- :disabled="loading"
- @click="removeFile"
- >{{ $options.i18n.REMOVE_FILE_TEXT }}</gl-button
- >
- </div>
- </upload-dropzone>
- <gl-form-group :label="$options.i18n.COMMIT_LABEL" label-for="commit_message">
- <gl-form-textarea v-model="commit" name="commit_message" :disabled="loading" />
- </gl-form-group>
- <gl-form-group
- v-if="canPushCode"
- :label="$options.i18n.TARGET_BRANCH_LABEL"
- label-for="branch_name"
- >
- <gl-form-input v-model="target" :disabled="loading" name="branch_name" />
- </gl-form-group>
- <gl-toggle
- v-if="showCreateNewMrToggle"
- v-model="createNewMr"
- :disabled="loading"
- :label="$options.i18n.TOGGLE_CREATE_MR_LABEL"
- />
- <gl-alert v-if="!canPushCode" variant="info" :dismissible="false" class="gl-mt-3">
- {{ $options.i18n.NEW_BRANCH_IN_FORK }}
- </gl-alert>
- </gl-modal>
- </gl-form>
-</template>
diff --git a/app/assets/javascripts/repository/index.js b/app/assets/javascripts/repository/index.js
index fafc6e8eb89..747b85f5c1c 100644
--- a/app/assets/javascripts/repository/index.js
+++ b/app/assets/javascripts/repository/index.js
@@ -1,8 +1,8 @@
import Vue from 'vue';
-import { parseBoolean } from '~/lib/utils/common_utils';
-import { escapeFileUrl } from '~/lib/utils/url_utility';
-import { __ } from '~/locale';
import initWebIdeLink from '~/pages/projects/shared/web_ide_link';
+import { parseBoolean } from '../lib/utils/common_utils';
+import { escapeFileUrl } from '../lib/utils/url_utility';
+import { __ } from '../locale';
import App from './components/app.vue';
import Breadcrumbs from './components/breadcrumbs.vue';
import DirectoryDownloadLinks from './components/directory_download_links.vue';
@@ -55,8 +55,6 @@ export default function setupVueRepositoryList() {
const {
canCollaborate,
canEditTree,
- canPushCode,
- selectedBranch,
newBranchPath,
newTagPath,
newBlobPath,
@@ -67,7 +65,8 @@ export default function setupVueRepositoryList() {
newDirPath,
} = breadcrumbEl.dataset;
- router.afterEach(({ params: { path } }) => {
+ router.afterEach(({ params: { path = '/' } }) => {
+ updateFormAction('.js-upload-blob-form', uploadPath, path);
updateFormAction('.js-create-dir-form', newDirPath, path);
});
@@ -82,16 +81,12 @@ export default function setupVueRepositoryList() {
currentPath: this.$route.params.path,
canCollaborate: parseBoolean(canCollaborate),
canEditTree: parseBoolean(canEditTree),
- canPushCode: parseBoolean(canPushCode),
- origionalBranch: ref,
- selectedBranch,
newBranchPath,
newTagPath,
newBlobPath,
forkNewBlobPath,
forkNewDirectoryPath,
forkUploadBlobPath,
- uploadPath,
},
});
},
diff --git a/app/assets/stylesheets/page_bundles/boards.scss b/app/assets/stylesheets/page_bundles/boards.scss
index 1cca42f94b2..e0543c5683b 100644
--- a/app/assets/stylesheets/page_bundles/boards.scss
+++ b/app/assets/stylesheets/page_bundles/boards.scss
@@ -37,6 +37,10 @@
}
}
+[data-page$='epic_boards:show'] .filter-form {
+ display: none;
+}
+
.boards-app {
@include media-breakpoint-up(sm) {
transition: width $sidebar-transition-duration;
diff --git a/app/controllers/projects/forks_controller.rb b/app/controllers/projects/forks_controller.rb
index 5576d5766c7..33f046f414f 100644
--- a/app/controllers/projects/forks_controller.rb
+++ b/app/controllers/projects/forks_controller.rb
@@ -16,6 +16,10 @@ class Projects::ForksController < Projects::ApplicationController
feature_category :source_code_management
+ before_action do
+ push_frontend_feature_flag(:fork_project_form)
+ end
+
def index
@total_forks_count = project.forks.size
@public_forks_count = project.forks.public_only.size
diff --git a/app/graphql/types/todo_action_enum.rb b/app/graphql/types/todo_action_enum.rb
index 0e538838474..ef43b6eb464 100644
--- a/app/graphql/types/todo_action_enum.rb
+++ b/app/graphql/types/todo_action_enum.rb
@@ -2,12 +2,14 @@
module Types
class TodoActionEnum < BaseEnum
- value 'assigned', value: 1
- value 'mentioned', value: 2
- value 'build_failed', value: 3
- value 'marked', value: 4
- value 'approval_required', value: 5
- value 'unmergeable', value: 6
- value 'directly_addressed', value: 7
+ value 'assigned', value: 1, description: 'User was assigned.'
+ value 'mentioned', value: 2, description: 'User was mentioned.'
+ value 'build_failed', value: 3, description: 'Build triggered by the user failed.'
+ value 'marked', value: 4, description: 'User added a TODO.'
+ value 'approval_required', value: 5, description: 'User was set as an approver.'
+ value 'unmergeable', value: 6, description: 'Merge request authored by the user could not be merged.'
+ value 'directly_addressed', value: 7, description: 'User was directly addressed.'
+ value 'merge_train_removed', value: 8, description: 'Merge request authored by the user was removed from the merge train.'
+ value 'review_requested', value: 9, description: 'Review was requested from the user.'
end
end
diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb
index b795851ba30..b050f533d77 100644
--- a/app/helpers/tree_helper.rb
+++ b/app/helpers/tree_helper.rb
@@ -131,8 +131,6 @@ module TreeHelper
def breadcrumb_data_attributes
attrs = {
- selected_branch: selected_branch,
- can_push_code: can?(current_user, :push_code, @project).to_s,
can_collaborate: can_collaborate_with_project?(@project).to_s,
new_blob_path: project_new_blob_path(@project, @ref),
upload_path: project_create_blob_path(@project, @ref),
diff --git a/app/views/dashboard/projects/_projects.html.haml b/app/views/dashboard/projects/_projects.html.haml
index 5122164dbcb..06ef89e0b57 100644
--- a/app/views/dashboard/projects/_projects.html.haml
+++ b/app/views/dashboard/projects/_projects.html.haml
@@ -1 +1 @@
-= render 'shared/projects/list', projects: @projects, pipeline_status: Feature.enabled?(:dashboard_pipeline_status, default_enabled: true), user: current_user
+= render 'shared/projects/list', projects: @projects, pipeline_status: true, user: current_user
diff --git a/app/views/projects/_files.html.haml b/app/views/projects/_files.html.haml
index 0369ee50c40..30d885964b5 100644
--- a/app/views/projects/_files.html.haml
+++ b/app/views/projects/_files.html.haml
@@ -21,4 +21,5 @@
#js-tree-list{ data: vue_file_list_data(project, ref) }
- if can_edit_tree?
+ = render 'projects/blob/upload', title: _('Upload New File'), placeholder: _('Upload New File'), button_title: _('Upload file'), form_path: project_create_blob_path(@project, @id), method: :post
= render 'projects/blob/new_dir'
diff --git a/app/views/projects/forks/new.html.haml b/app/views/projects/forks/new.html.haml
index ccef28a2cf3..562aa0fd353 100644
--- a/app/views/projects/forks/new.html.haml
+++ b/app/views/projects/forks/new.html.haml
@@ -9,10 +9,20 @@
%br
= _('Forking a repository allows you to make changes without affecting the original project.')
.col-lg-9
- - if @own_namespace.present?
- .fork-thumbnail-container.js-fork-content
- %h5.gl-mt-0.gl-mb-0.gl-ml-3.gl-mr-3
- = _("Select a namespace to fork the project")
- = render 'fork_button', namespace: @own_namespace
- #fork-groups-mount-element{ data: { endpoint: new_project_fork_path(@project, format: :json) } }
-
+ - if Feature.enabled?(:fork_project_form)
+ #fork-groups-mount-element{ data: { endpoint: new_project_fork_path(@project, format: :json),
+ new_group_path: new_group_path,
+ project_full_path: project_path(@project),
+ visibility_help_path: help_page_path("public_access/public_access"),
+ project_id: @project.id,
+ project_name: @project.name,
+ project_path: @project.path,
+ project_description: @project.description,
+ project_visibility: @project.visibility } }
+ - else
+ - if @own_namespace.present?
+ .fork-thumbnail-container.js-fork-content
+ %h5.gl-mt-0.gl-mb-0.gl-ml-3.gl-mr-3
+ = _("Select a namespace to fork the project")
+ = render 'fork_button', namespace: @own_namespace
+ #fork-groups-mount-element{ data: { endpoint: new_project_fork_path(@project, format: :json) } }
diff --git a/app/views/projects/runners/_runner.html.haml b/app/views/projects/runners/_runner.html.haml
index 41159df1435..7f5acbbe890 100644
--- a/app/views/projects/runners/_runner.html.haml
+++ b/app/views/projects/runners/_runner.html.haml
@@ -40,5 +40,5 @@
- if runner.tags.present?
%p
- runner.tags.map(&:name).sort.each do |tag|
- %span.badge.badge-primary
+ %span.badge.gl-badge.sm.badge-pill.badge-primary
= tag