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:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-10-07 21:11:28 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-10-07 21:11:28 +0300
commit5a71c032e8e0dcb5593df5c257c88487e332e5e5 (patch)
treef18718e7e11658efd66709ee5947e6d054470e4c /app/assets
parentc3524d16b2ef6a13fd6b398aaeae9af5462f1e33 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets')
-rw-r--r--app/assets/javascripts/ide/components/jobs/detail.vue2
-rw-r--r--app/assets/javascripts/jobs/components/job_app.vue2
-rw-r--r--app/assets/javascripts/logs/components/environment_logs.vue2
-rw-r--r--app/assets/javascripts/pages/projects/new/components/new_project_url_select.vue73
-rw-r--r--app/assets/javascripts/pages/projects/new/event_hub.js3
-rw-r--r--app/assets/javascripts/pages/projects/new/index.js37
-rw-r--r--app/assets/javascripts/repository/components/blob_content_viewer.vue40
-rw-r--r--app/assets/javascripts/repository/components/blob_edit.vue16
-rw-r--r--app/assets/javascripts/repository/queries/blob_info.query.graphql5
-rw-r--r--app/assets/javascripts/vue_shared/components/web_ide_link.vue10
-rw-r--r--app/assets/stylesheets/bootstrap_migration.scss2
-rw-r--r--app/assets/stylesheets/framework/job_log.scss4
-rw-r--r--app/assets/stylesheets/framework/mixins.scss10
-rw-r--r--app/assets/stylesheets/framework/variables.scss2
-rw-r--r--app/assets/stylesheets/page_bundles/_ide_mixins.scss2
-rw-r--r--app/assets/stylesheets/page_bundles/build.scss6
-rw-r--r--app/assets/stylesheets/page_bundles/pipeline.scss14
-rw-r--r--app/assets/stylesheets/pages/environment_logs.scss4
18 files changed, 173 insertions, 61 deletions
diff --git a/app/assets/javascripts/ide/components/jobs/detail.vue b/app/assets/javascripts/ide/components/jobs/detail.vue
index cc54dd52561..96cb4f3d495 100644
--- a/app/assets/javascripts/ide/components/jobs/detail.vue
+++ b/app/assets/javascripts/ide/components/jobs/detail.vue
@@ -97,7 +97,7 @@ export default {
<scroll-button :disabled="isScrolledToBottom" direction="down" @click="scrollDown" />
</div>
</div>
- <pre ref="buildJobLog" class="build-trace mb-0 h-100 mr-3" @scroll="scrollBuildLog">
+ <pre ref="buildJobLog" class="build-log mb-0 h-100 mr-3" @scroll="scrollBuildLog">
<code
v-show="!detailJob.isLoading"
class="bash"
diff --git a/app/assets/javascripts/jobs/components/job_app.vue b/app/assets/javascripts/jobs/components/job_app.vue
index 2914e4918df..fe4158a1bd1 100644
--- a/app/assets/javascripts/jobs/components/job_app.vue
+++ b/app/assets/javascripts/jobs/components/job_app.vue
@@ -279,7 +279,7 @@ export default {
<!-- job log -->
<div
v-if="hasJobLog"
- class="build-trace-container gl-relative"
+ class="build-log-container gl-relative"
:class="{ 'gl-mt-3': !job.archived }"
>
<log-top-bar
diff --git a/app/assets/javascripts/logs/components/environment_logs.vue b/app/assets/javascripts/logs/components/environment_logs.vue
index 3db9fa01629..2a60825a427 100644
--- a/app/assets/javascripts/logs/components/environment_logs.vue
+++ b/app/assets/javascripts/logs/components/environment_logs.vue
@@ -214,7 +214,7 @@ export default {
<template #items>
<pre
ref="logTrace"
- class="build-trace"
+ class="build-log"
><code class="bash js-build-output"><div v-if="showLoader" class="build-loader-animation js-build-loader-animation">
<div class="dot"></div>
<div class="dot"></div>
diff --git a/app/assets/javascripts/pages/projects/new/components/new_project_url_select.vue b/app/assets/javascripts/pages/projects/new/components/new_project_url_select.vue
index c30d3ec5db4..e2572183082 100644
--- a/app/assets/javascripts/pages/projects/new/components/new_project_url_select.vue
+++ b/app/assets/javascripts/pages/projects/new/components/new_project_url_select.vue
@@ -14,6 +14,7 @@ import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import Tracking from '~/tracking';
import { DEBOUNCE_DELAY } from '~/vue_shared/components/filtered_search_bar/constants';
import searchNamespacesWhereUserCanCreateProjectsQuery from '../queries/search_namespaces_where_user_can_create_projects.query.graphql';
+import eventHub from '../event_hub';
export default {
components: {
@@ -41,15 +42,28 @@ export default {
debounce: DEBOUNCE_DELAY,
},
},
- inject: ['namespaceFullPath', 'namespaceId', 'rootUrl', 'trackLabel'],
+ inject: [
+ 'namespaceFullPath',
+ 'namespaceId',
+ 'rootUrl',
+ 'trackLabel',
+ 'userNamespaceFullPath',
+ 'userNamespaceId',
+ ],
data() {
return {
currentUser: {},
+ groupToFilterBy: undefined,
search: '',
- selectedNamespace: {
- id: this.namespaceId,
- fullPath: this.namespaceFullPath,
- },
+ selectedNamespace: this.namespaceId
+ ? {
+ id: this.namespaceId,
+ fullPath: this.namespaceFullPath,
+ }
+ : {
+ id: this.userNamespaceId,
+ fullPath: this.userNamespaceFullPath,
+ },
};
},
computed: {
@@ -59,21 +73,43 @@ export default {
userNamespace() {
return this.currentUser.namespace || {};
},
+ filteredGroups() {
+ return this.groupToFilterBy
+ ? this.userGroups.filter((group) =>
+ group.fullPath.startsWith(this.groupToFilterBy.fullPath),
+ )
+ : this.userGroups;
+ },
hasGroupMatches() {
- return this.userGroups.length;
+ return this.filteredGroups.length;
},
hasNamespaceMatches() {
- return this.userNamespace.fullPath?.toLowerCase().includes(this.search.toLowerCase());
+ return (
+ this.userNamespace.fullPath?.toLowerCase().includes(this.search.toLowerCase()) &&
+ !this.groupToFilterBy
+ );
},
hasNoMatches() {
return !this.hasGroupMatches && !this.hasNamespaceMatches;
},
},
+ created() {
+ eventHub.$on('select-template', this.handleSelectTemplate);
+ },
+ beforeDestroy() {
+ eventHub.$off('select-template', this.handleSelectTemplate);
+ },
methods: {
focusInput() {
this.$refs.search.focusInput();
},
- handleClick({ id, fullPath }) {
+ handleSelectTemplate(groupId) {
+ this.groupToFilterBy = this.userGroups.find(
+ (group) => getIdFromGraphQLId(group.id) === groupId,
+ );
+ this.setNamespace(this.groupToFilterBy);
+ },
+ setNamespace({ id, fullPath }) {
this.selectedNamespace = {
id: getIdFromGraphQLId(id),
fullPath,
@@ -84,28 +120,35 @@ export default {
</script>
<template>
- <gl-button-group class="gl-w-full">
- <gl-button label>{{ rootUrl }}</gl-button>
+ <gl-button-group class="input-lg">
+ <gl-button class="gl-text-truncate" label :title="rootUrl">{{ rootUrl }}</gl-button>
<gl-dropdown
- class="gl-w-full"
:text="selectedNamespace.fullPath"
- toggle-class="gl-rounded-top-right-base! gl-rounded-bottom-right-base!"
+ toggle-class="gl-rounded-top-right-base! gl-rounded-bottom-right-base! gl-w-20"
data-qa-selector="select_namespace_dropdown"
@show="track('activate_form_input', { label: trackLabel, property: 'project_path' })"
@shown="focusInput"
>
- <gl-search-box-by-type ref="search" v-model.trim="search" />
+ <gl-search-box-by-type
+ ref="search"
+ v-model.trim="search"
+ data-qa-selector="select_namespace_dropdown_search_field"
+ />
<gl-loading-icon v-if="$apollo.queries.currentUser.loading" />
<template v-else>
<template v-if="hasGroupMatches">
<gl-dropdown-section-header>{{ __('Groups') }}</gl-dropdown-section-header>
- <gl-dropdown-item v-for="group of userGroups" :key="group.id" @click="handleClick(group)">
+ <gl-dropdown-item
+ v-for="group of filteredGroups"
+ :key="group.id"
+ @click="setNamespace(group)"
+ >
{{ group.fullPath }}
</gl-dropdown-item>
</template>
<template v-if="hasNamespaceMatches">
<gl-dropdown-section-header>{{ __('Users') }}</gl-dropdown-section-header>
- <gl-dropdown-item @click="handleClick(userNamespace)">
+ <gl-dropdown-item @click="setNamespace(userNamespace)">
{{ userNamespace.fullPath }}
</gl-dropdown-item>
</template>
diff --git a/app/assets/javascripts/pages/projects/new/event_hub.js b/app/assets/javascripts/pages/projects/new/event_hub.js
new file mode 100644
index 00000000000..e31806ad199
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/new/event_hub.js
@@ -0,0 +1,3 @@
+import createEventHub from '~/helpers/event_hub_factory';
+
+export default createEventHub();
diff --git a/app/assets/javascripts/pages/projects/new/index.js b/app/assets/javascripts/pages/projects/new/index.js
index ed816e3be95..e43847caa5f 100644
--- a/app/assets/javascripts/pages/projects/new/index.js
+++ b/app/assets/javascripts/pages/projects/new/index.js
@@ -39,27 +39,32 @@ function initNewProjectCreation() {
}
function initNewProjectUrlSelect() {
- const el = document.querySelector('.js-vue-new-project-url-select');
+ const elements = document.querySelectorAll('.js-vue-new-project-url-select');
- if (!el) {
- return undefined;
+ if (!elements.length) {
+ return;
}
Vue.use(VueApollo);
- return new Vue({
- el,
- apolloProvider: new VueApollo({
- defaultClient: createDefaultClient({}, { assumeImmutableResults: true }),
- }),
- provide: {
- namespaceFullPath: el.dataset.namespaceFullPath,
- namespaceId: el.dataset.namespaceId,
- rootUrl: el.dataset.rootUrl,
- trackLabel: el.dataset.trackLabel,
- },
- render: (createElement) => createElement(NewProjectUrlSelect),
- });
+ elements.forEach(
+ (el) =>
+ new Vue({
+ el,
+ apolloProvider: new VueApollo({
+ defaultClient: createDefaultClient({}, { assumeImmutableResults: true }),
+ }),
+ provide: {
+ namespaceFullPath: el.dataset.namespaceFullPath,
+ namespaceId: el.dataset.namespaceId,
+ rootUrl: el.dataset.rootUrl,
+ trackLabel: el.dataset.trackLabel,
+ userNamespaceFullPath: el.dataset.userNamespaceFullPath,
+ userNamespaceId: el.dataset.userNamespaceId,
+ },
+ render: (createElement) => createElement(NewProjectUrlSelect),
+ }),
+ );
}
initProjectVisibilitySelector();
diff --git a/app/assets/javascripts/repository/components/blob_content_viewer.vue b/app/assets/javascripts/repository/components/blob_content_viewer.vue
index 8891cdc40c0..7ad9fb56972 100644
--- a/app/assets/javascripts/repository/components/blob_content_viewer.vue
+++ b/app/assets/javascripts/repository/components/blob_content_viewer.vue
@@ -8,10 +8,12 @@ import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import { isLoggedIn } from '~/lib/utils/common_utils';
import { __ } from '~/locale';
+import { redirectTo } from '~/lib/utils/url_utility';
import getRefMixin from '../mixins/get_ref';
import blobInfoQuery from '../queries/blob_info.query.graphql';
import BlobButtonGroup from './blob_button_group.vue';
import BlobEdit from './blob_edit.vue';
+import ForkSuggestion from './fork_suggestion.vue';
import { loadViewer, viewerProps } from './blob_viewers';
export default {
@@ -21,6 +23,7 @@ export default {
BlobButtonGroup,
BlobContent,
GlLoadingIcon,
+ ForkSuggestion,
},
mixins: [getRefMixin],
inject: {
@@ -65,6 +68,7 @@ export default {
},
data() {
return {
+ forkTarget: null,
legacyRichViewer: null,
legacySimpleViewer: null,
isBinary: false,
@@ -74,6 +78,8 @@ export default {
userPermissions: {
pushCode: false,
downloadCode: false,
+ createMergeRequestIn: false,
+ forkProject: false,
},
pathLocks: {
nodes: [],
@@ -92,12 +98,14 @@ export default {
path: '',
editBlobPath: '',
ideEditPath: '',
+ forkAndEditPath: '',
+ ideForkAndEditPath: '',
storedExternally: false,
+ canModifyBlob: false,
rawPath: '',
externalStorageUrl: '',
replacePath: '',
deletePath: '',
- forkPath: '',
simpleViewer: {},
richViewer: null,
webPath: '',
@@ -149,6 +157,17 @@ export default {
isLocked() {
return this.project.pathLocks.nodes.some((node) => node.path === this.path);
},
+ showForkSuggestion() {
+ const { createMergeRequestIn, forkProject } = this.project.userPermissions;
+ const { canModifyBlob } = this.blobInfo;
+
+ return this.isLoggedIn && !canModifyBlob && createMergeRequestIn && forkProject;
+ },
+ forkPath() {
+ return this.forkTarget === 'ide'
+ ? this.blobInfo.ideForkAndEditPath
+ : this.blobInfo.forkAndEditPath;
+ },
},
methods: {
loadLegacyViewer(type) {
@@ -187,6 +206,18 @@ export default {
this.loadLegacyViewer(this.activeViewerType);
}
},
+ editBlob(target) {
+ if (this.showForkSuggestion) {
+ this.setForkTarget(target);
+ return;
+ }
+
+ const { ideEditPath, editBlobPath } = this.blobInfo;
+ redirectTo(target === 'ide' ? ideEditPath : editBlobPath);
+ },
+ setForkTarget(target) {
+ this.forkTarget = target;
+ },
},
};
</script>
@@ -208,6 +239,8 @@ export default {
:show-edit-button="!isBinaryFileType"
:edit-path="blobInfo.editBlobPath"
:web-ide-path="blobInfo.ideEditPath"
+ :needs-to-fork="showForkSuggestion"
+ @edit="editBlob"
/>
<blob-button-group
v-if="isLoggedIn"
@@ -223,6 +256,11 @@ export default {
/>
</template>
</blob-header>
+ <fork-suggestion
+ v-if="forkTarget && showForkSuggestion"
+ :fork-path="forkPath"
+ @cancel="setForkTarget(null)"
+ />
<blob-content
v-if="!blobViewer"
:rich-viewer="legacyRichViewer"
diff --git a/app/assets/javascripts/repository/components/blob_edit.vue b/app/assets/javascripts/repository/components/blob_edit.vue
index 30ed4cd57f1..fd377ba1b81 100644
--- a/app/assets/javascripts/repository/components/blob_edit.vue
+++ b/app/assets/javascripts/repository/components/blob_edit.vue
@@ -27,6 +27,16 @@ export default {
type: String,
required: true,
},
+ needsToFork: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ methods: {
+ onEdit(target) {
+ this.$emit('edit', target);
+ },
},
};
</script>
@@ -38,7 +48,9 @@ export default {
class="gl-mr-3"
:edit-url="editPath"
:web-ide-url="webIdePath"
+ :needs-to-fork="needsToFork"
:is-blob="true"
+ @edit="onEdit"
/>
<div v-else>
<gl-button
@@ -46,8 +58,8 @@ export default {
class="gl-mr-2"
category="primary"
variant="confirm"
- :href="editPath"
data-testid="edit"
+ @click="onEdit('simple')"
>
{{ $options.i18n.edit }}
</gl-button>
@@ -56,8 +68,8 @@ export default {
class="gl-mr-3"
category="primary"
variant="confirm"
- :href="webIdePath"
data-testid="web-ide"
+ @click="onEdit('ide')"
>
{{ $options.i18n.webIde }}
</gl-button>
diff --git a/app/assets/javascripts/repository/queries/blob_info.query.graphql b/app/assets/javascripts/repository/queries/blob_info.query.graphql
index 45f07f7dc58..8e0b5e21ca3 100644
--- a/app/assets/javascripts/repository/queries/blob_info.query.graphql
+++ b/app/assets/javascripts/repository/queries/blob_info.query.graphql
@@ -4,6 +4,8 @@ query getBlobInfo($projectPath: ID!, $filePath: String!, $ref: String!) {
userPermissions {
pushCode
downloadCode
+ createMergeRequestIn
+ forkProject
}
pathLocks {
nodes {
@@ -23,6 +25,9 @@ query getBlobInfo($projectPath: ID!, $filePath: String!, $ref: String!) {
path
editBlobPath
ideEditPath
+ forkAndEditPath
+ ideForkAndEditPath
+ canModifyBlob
storedExternally
rawPath
replacePath
diff --git a/app/assets/javascripts/vue_shared/components/web_ide_link.vue b/app/assets/javascripts/vue_shared/components/web_ide_link.vue
index df0981aea7a..6da2d39a95a 100644
--- a/app/assets/javascripts/vue_shared/components/web_ide_link.vue
+++ b/app/assets/javascripts/vue_shared/components/web_ide_link.vue
@@ -92,7 +92,10 @@ export default {
const handleOptions = this.needsToFork
? {
href: '#modal-confirm-fork-edit',
- handle: () => this.showModal('#modal-confirm-fork-edit'),
+ handle: () => {
+ this.$emit('edit', 'simple');
+ this.showModal('#modal-confirm-fork-edit');
+ },
}
: { href: this.editUrl };
@@ -128,7 +131,10 @@ export default {
const handleOptions = this.needsToFork
? {
href: '#modal-confirm-fork-webide',
- handle: () => this.showModal('#modal-confirm-fork-webide'),
+ handle: () => {
+ this.$emit('edit', 'ide');
+ this.showModal('#modal-confirm-fork-webide');
+ },
}
: { href: this.webIdeUrl };
diff --git a/app/assets/stylesheets/bootstrap_migration.scss b/app/assets/stylesheets/bootstrap_migration.scss
index c4f292dd05d..27ddff181c5 100644
--- a/app/assets/stylesheets/bootstrap_migration.scss
+++ b/app/assets/stylesheets/bootstrap_migration.scss
@@ -112,7 +112,7 @@ code {
border-radius: $border-radius-default;
.code > &,
- .build-trace & {
+ .build-log & {
background-color: inherit;
padding: unset;
}
diff --git a/app/assets/stylesheets/framework/job_log.scss b/app/assets/stylesheets/framework/job_log.scss
index 0a493b3a977..f77f64f1d76 100644
--- a/app/assets/stylesheets/framework/job_log.scss
+++ b/app/assets/stylesheets/framework/job_log.scss
@@ -5,10 +5,10 @@
font-size: 13px;
word-break: break-all;
word-wrap: break-word;
- color: color-yiq($builds-trace-bg);
+ color: color-yiq($builds-log-bg);
border-radius: $border-radius-small;
min-height: 42px;
- background-color: $builds-trace-bg;
+ background-color: $builds-log-bg;
}
.log-line {
diff --git a/app/assets/stylesheets/framework/mixins.scss b/app/assets/stylesheets/framework/mixins.scss
index fcf86680bb3..33f7aa4dba1 100644
--- a/app/assets/stylesheets/framework/mixins.scss
+++ b/app/assets/stylesheets/framework/mixins.scss
@@ -239,7 +239,7 @@
/*
* Mixin that handles the container for the job logs (CI/CD and kubernetes pod logs)
*/
-@mixin build-trace($background: $black) {
+@mixin build-log($background: $black) {
background: $background;
color: $gray-darkest;
white-space: pre;
@@ -253,13 +253,13 @@
display: block;
}
- &.build-trace-rounded {
+ &.build-log-rounded {
border-radius: $gl-border-radius-base;
}
}
// Used in EE for Web Terminal
-@mixin build-trace-bar($height) {
+@mixin build-log-bar($height) {
height: $height;
min-height: $height;
background: var(--gray-50, $gray-50);
@@ -268,8 +268,8 @@
padding: $grid-size;
}
-@mixin build-trace-top-bar($height) {
- @include build-trace-bar($height);
+@mixin build-log-top-bar($height) {
+ @include build-log-bar($height);
position: -webkit-sticky;
position: sticky;
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index c0e297d8554..026aeeb1e8e 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -697,7 +697,7 @@ $blame-blue: #254e77;
/*
* Builds
*/
-$builds-trace-bg: #111;
+$builds-log-bg: #111;
$job-log-highlight-height: 18px;
$job-log-line-padding: 55px;
$job-line-number-width: 50px;
diff --git a/app/assets/stylesheets/page_bundles/_ide_mixins.scss b/app/assets/stylesheets/page_bundles/_ide_mixins.scss
index 48b8a7230b1..bbc47c5cd5d 100644
--- a/app/assets/stylesheets/page_bundles/_ide_mixins.scss
+++ b/app/assets/stylesheets/page_bundles/_ide_mixins.scss
@@ -4,7 +4,7 @@
height: 100%;
.top-bar {
- @include build-trace-bar(35px);
+ @include build-log-bar(35px);
top: 0;
font-size: 12px;
diff --git a/app/assets/stylesheets/page_bundles/build.scss b/app/assets/stylesheets/page_bundles/build.scss
index ec41909beec..ed62e055427 100644
--- a/app/assets/stylesheets/page_bundles/build.scss
+++ b/app/assets/stylesheets/page_bundles/build.scss
@@ -1,8 +1,8 @@
@import 'mixins_and_variables_and_functions';
.build-page {
- .build-trace {
- @include build-trace();
+ .build-log {
+ @include build-log();
}
.archived-job {
@@ -18,7 +18,7 @@
}
.top-bar {
- @include build-trace-top-bar(50px);
+ @include build-log-top-bar(50px);
&.has-archived-block {
top: $header-height + 28px;
diff --git a/app/assets/stylesheets/page_bundles/pipeline.scss b/app/assets/stylesheets/page_bundles/pipeline.scss
index 206c2eb09d0..c8b1b6cf9aa 100644
--- a/app/assets/stylesheets/page_bundles/pipeline.scss
+++ b/app/assets/stylesheets/page_bundles/pipeline.scss
@@ -44,14 +44,14 @@
line-height: initial;
}
- .build-trace-row td {
+ .build-log-row td {
border-top: 0;
border-bottom-width: 1px;
border-bottom-style: solid;
padding-top: 0;
}
- .build-trace {
+ .build-log {
width: 100%;
text-align: left;
margin-top: $gl-padding;
@@ -93,7 +93,7 @@
}
.build-state,
- .build-trace-row {
+ .build-log-row {
> td:last-child {
padding-right: 0;
}
@@ -108,12 +108,12 @@
margin-top: 2 * $gl-padding;
}
- .build-trace-container {
+ .build-log-container {
padding-top: $gl-padding;
padding-bottom: $gl-padding;
}
- .build-trace {
+ .build-log {
margin-bottom: 0;
margin-top: 0;
}
@@ -221,8 +221,8 @@
}
.test-reports-table {
- .build-trace {
- @include build-trace();
+ .build-log {
+ @include build-log();
}
}
diff --git a/app/assets/stylesheets/pages/environment_logs.scss b/app/assets/stylesheets/pages/environment_logs.scss
index 03993e5321d..f8f40076142 100644
--- a/app/assets/stylesheets/pages/environment_logs.scss
+++ b/app/assets/stylesheets/pages/environment_logs.scss
@@ -40,8 +40,8 @@
height: 100%;
}
- .build-trace {
- @include build-trace($black);
+ .build-log {
+ @include build-log($black);
}
.gl-infinite-scroll-legend {