...@@ -3,7 +3,7 @@ import $ from 'jquery'; ...@@ -3,7 +3,7 @@ import $ from 'jquery';
import { mapActions, mapGetters, mapState } from 'vuex'; import { mapActions, mapGetters, mapState } from 'vuex';
import Icon from '~/vue_shared/components/icon.vue'; import Icon from '~/vue_shared/components/icon.vue';
import tooltip from '~/vue_shared/directives/tooltip'; import tooltip from '~/vue_shared/directives/tooltip';
import { activityBarViews } from '../constants'; import { leftSidebarViews } from '../constants';
export default { export default {
components: { components: {
...@@ -26,7 +26,7 @@ export default { ...@@ -26,7 +26,7 @@ export default {
$(e.currentTarget).tooltip('hide'); $(e.currentTarget).tooltip('hide');
}, },
}, },
activityBarViews, leftSidebarViews,
}; };
</script> </script>
...@@ -37,7 +37,7 @@ export default { ...@@ -37,7 +37,7 @@ export default {
<button <button
v-tooltip v-tooltip
:class="{ :class="{
active: currentActivityView === $options.activityBarViews.edit, active: currentActivityView === $options.leftSidebarViews.edit.name,
}" }"
:title="s__('IDE|Edit')" :title="s__('IDE|Edit')"
:aria-label="s__('IDE|Edit')" :aria-label="s__('IDE|Edit')"
...@@ -45,7 +45,7 @@ export default { ...@@ -45,7 +45,7 @@ export default {
data-placement="right" data-placement="right"
type="button" type="button"
class="ide-sidebar-link js-ide-edit-mode" class="ide-sidebar-link js-ide-edit-mode"
@click.prevent="changedActivityView($event, $options.activityBarViews.edit)" @click.prevent="changedActivityView($event, $options.leftSidebarViews.edit.name)"
> >
<icon name="code" /> <icon name="code" />
</button> </button>
...@@ -54,7 +54,7 @@ export default { ...@@ -54,7 +54,7 @@ export default {
<button <button
v-tooltip v-tooltip
:class="{ :class="{
active: currentActivityView === $options.activityBarViews.review, active: currentActivityView === $options.leftSidebarViews.review.name,
}" }"
:title="s__('IDE|Review')" :title="s__('IDE|Review')"
:aria-label="s__('IDE|Review')" :aria-label="s__('IDE|Review')"
...@@ -62,7 +62,7 @@ export default { ...@@ -62,7 +62,7 @@ export default {
data-placement="right" data-placement="right"
type="button" type="button"
class="ide-sidebar-link js-ide-review-mode" class="ide-sidebar-link js-ide-review-mode"
@click.prevent="changedActivityView($event, $options.activityBarViews.review)" @click.prevent="changedActivityView($event, $options.leftSidebarViews.review.name)"
> >
<icon name="file-modified" /> <icon name="file-modified" />
</button> </button>
...@@ -71,7 +71,7 @@ export default { ...@@ -71,7 +71,7 @@ export default {
<button <button
v-tooltip v-tooltip
:class="{ :class="{
active: currentActivityView === $options.activityBarViews.commit, active: currentActivityView === $options.leftSidebarViews.commit.name,
}" }"
:title="s__('IDE|Commit')" :title="s__('IDE|Commit')"
:aria-label="s__('IDE|Commit')" :aria-label="s__('IDE|Commit')"
...@@ -79,7 +79,7 @@ export default { ...@@ -79,7 +79,7 @@ export default {
data-placement="right" data-placement="right"
type="button" type="button"
class="ide-sidebar-link js-ide-commit-mode qa-commit-mode-tab" class="ide-sidebar-link js-ide-commit-mode qa-commit-mode-tab"
@click.prevent="changedActivityView($event, $options.activityBarViews.commit)" @click.prevent="changedActivityView($event, $options.leftSidebarViews.commit.name)"
> >
<icon name="commit" /> <icon name="commit" />
</button> </button>
... ...
......
...@@ -5,7 +5,7 @@ import LoadingButton from '~/vue_shared/components/loading_button.vue'; ...@@ -5,7 +5,7 @@ import LoadingButton from '~/vue_shared/components/loading_button.vue';
import CommitMessageField from './message_field.vue'; import CommitMessageField from './message_field.vue';
import Actions from './actions.vue'; import Actions from './actions.vue';
import SuccessMessage from './success_message.vue'; import SuccessMessage from './success_message.vue';
import { activityBarViews, MAX_WINDOW_HEIGHT_COMPACT } from '../../constants'; import { leftSidebarViews, MAX_WINDOW_HEIGHT_COMPACT } from '../../constants';
export default { export default {
components: { components: {
...@@ -41,7 +41,7 @@ export default { ...@@ -41,7 +41,7 @@ export default {
}, },
currentViewIsCommitView() { currentViewIsCommitView() {
return this.currentActivityView === activityBarViews.commit; return this.currentActivityView === leftSidebarViews.commit.name;
}, },
}, },
watch: { watch: {
...@@ -57,7 +57,7 @@ export default { ...@@ -57,7 +57,7 @@ export default {
lastCommitMsg() { lastCommitMsg() {
this.isCompact = this.isCompact =
this.currentActivityView !== activityBarViews.commit && this.lastCommitMsg === ''; this.currentActivityView !== leftSidebarViews.commit.name && this.lastCommitMsg === '';
}, },
}, },
methods: { methods: {
...@@ -67,7 +67,7 @@ export default { ...@@ -67,7 +67,7 @@ export default {
if (this.currentViewIsCommitView) { if (this.currentViewIsCommitView) {
this.isCompact = !this.isCompact; this.isCompact = !this.isCompact;
} else { } else {
this.updateActivityBarView(activityBarViews.commit) this.updateActivityBarView(leftSidebarViews.commit.name)
.then(() => { .then(() => {
this.isCompact = false; this.isCompact = false;
}) })
... ...
......
...@@ -4,19 +4,19 @@ import { GlSkeletonLoading } from '@gitlab/ui'; ...@@ -4,19 +4,19 @@ import { GlSkeletonLoading } from '@gitlab/ui';
import IdeTree from './ide_tree.vue'; import IdeTree from './ide_tree.vue';
import ResizablePanel from './resizable_panel.vue'; import ResizablePanel from './resizable_panel.vue';
import ActivityBar from './activity_bar.vue'; import ActivityBar from './activity_bar.vue';
import CommitSection from './repo_commit_section.vue'; import RepoCommitSection from './repo_commit_section.vue';
import CommitForm from './commit_sidebar/form.vue'; import CommitForm from './commit_sidebar/form.vue';
import IdeReview from './ide_review.vue'; import IdeReview from './ide_review.vue';
import SuccessMessage from './commit_sidebar/success_message.vue'; import SuccessMessage from './commit_sidebar/success_message.vue';
import IdeProjectHeader from './ide_project_header.vue'; import IdeProjectHeader from './ide_project_header.vue';
import { activityBarViews } from '../constants'; import { leftSidebarViews } from '../constants';
export default { export default {
components: { components: {
GlSkeletonLoading, GlSkeletonLoading,
ResizablePanel, ResizablePanel,
ActivityBar, ActivityBar,
CommitSection, RepoCommitSection,
IdeTree, IdeTree,
CommitForm, CommitForm,
IdeReview, IdeReview,
...@@ -28,7 +28,7 @@ export default { ...@@ -28,7 +28,7 @@ export default {
...mapGetters(['currentProject', 'someUncommittedChanges']), ...mapGetters(['currentProject', 'someUncommittedChanges']),
showSuccessMessage() { showSuccessMessage() {
return ( return (
this.currentActivityView === activityBarViews.edit && this.currentActivityView === leftSidebarViews.edit.name &&
(this.lastCommitMsg && !this.someUncommittedChanges) (this.lastCommitMsg && !this.someUncommittedChanges)
); );
}, },
... ...
......
...@@ -5,7 +5,7 @@ import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue'; ...@@ -5,7 +5,7 @@ import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
import CommitFilesList from './commit_sidebar/list.vue'; import CommitFilesList from './commit_sidebar/list.vue';
import EmptyState from './commit_sidebar/empty_state.vue'; import EmptyState from './commit_sidebar/empty_state.vue';
import consts from '../stores/modules/commit/constants'; import consts from '../stores/modules/commit/constants';
import { activityBarViews, stageKeys } from '../constants'; import { leftSidebarViews, stageKeys } from '../constants';
export default { export default {
components: { components: {
...@@ -37,7 +37,7 @@ export default { ...@@ -37,7 +37,7 @@ export default {
watch: { watch: {
hasChanges() { hasChanges() {
if (!this.hasChanges) { if (!this.hasChanges) {
this.updateActivityBarView(activityBarViews.edit); this.updateActivityBarView(leftSidebarViews.edit.name);
} }
}, },
}, },
... ...
......
...@@ -5,7 +5,7 @@ import flash from '~/flash'; ...@@ -5,7 +5,7 @@ import flash from '~/flash';
import ContentViewer from '~/vue_shared/components/content_viewer/content_viewer.vue'; import ContentViewer from '~/vue_shared/components/content_viewer/content_viewer.vue';
import DiffViewer from '~/vue_shared/components/diff_viewer/diff_viewer.vue'; import DiffViewer from '~/vue_shared/components/diff_viewer/diff_viewer.vue';
import { import {
activityBarViews, leftSidebarViews,
viewerTypes, viewerTypes,
FILE_VIEW_MODE_EDITOR, FILE_VIEW_MODE_EDITOR,
FILE_VIEW_MODE_PREVIEW, FILE_VIEW_MODE_PREVIEW,
...@@ -100,7 +100,7 @@ export default { ...@@ -100,7 +100,7 @@ export default {
if (oldVal.key !== this.file.key) { if (oldVal.key !== this.file.key) {
this.initEditor(); this.initEditor();
if (this.currentActivityView !== activityBarViews.edit) { if (this.currentActivityView !== leftSidebarViews.edit.name) {
this.setFileViewMode({ this.setFileViewMode({
file: this.file, file: this.file,
viewMode: FILE_VIEW_MODE_EDITOR, viewMode: FILE_VIEW_MODE_EDITOR,
...@@ -109,7 +109,7 @@ export default { ...@@ -109,7 +109,7 @@ export default {
} }
}, },
currentActivityView() { currentActivityView() {
if (this.currentActivityView !== activityBarViews.edit) { if (this.currentActivityView !== leftSidebarViews.edit.name) {
this.setFileViewMode({ this.setFileViewMode({
file: this.file, file: this.file,
viewMode: FILE_VIEW_MODE_EDITOR, viewMode: FILE_VIEW_MODE_EDITOR,
... ...
......
...@@ -11,12 +11,6 @@ export const FILE_VIEW_MODE_PREVIEW = 'preview'; ...@@ -11,12 +11,6 @@ export const FILE_VIEW_MODE_PREVIEW = 'preview';
export const PERMISSION_CREATE_MR = 'createMergeRequestIn'; export const PERMISSION_CREATE_MR = 'createMergeRequestIn';
export const PERMISSION_READ_MR = 'readMergeRequest'; export const PERMISSION_READ_MR = 'readMergeRequest';
export const activityBarViews = {
edit: 'ide-tree',
commit: 'commit-section',
review: 'ide-review',
};
export const viewerTypes = { export const viewerTypes = {
mr: 'mrdiff', mr: 'mrdiff',
edit: 'editor', edit: 'editor',
...@@ -47,6 +41,12 @@ export const diffViewerErrors = Object.freeze({ ...@@ -47,6 +41,12 @@ export const diffViewerErrors = Object.freeze({
stored_externally: 'server_side_but_stored_externally', stored_externally: 'server_side_but_stored_externally',
}); });
export const leftSidebarViews = {
edit: { name: 'ide-tree', keepAlive: false },
review: { name: 'ide-review', keepAlive: false },
commit: { name: 'repo-commit-section', keepAlive: false },
};
export const rightSidebarViews = { export const rightSidebarViews = {
pipelines: { name: 'pipelines-list', keepAlive: true }, pipelines: { name: 'pipelines-list', keepAlive: true },
jobsDetail: { name: 'jobs-detail', keepAlive: false }, jobsDetail: { name: 'jobs-detail', keepAlive: false },
... ...
......
...@@ -2,7 +2,7 @@ import flash from '~/flash'; ...@@ -2,7 +2,7 @@ import flash from '~/flash';
import { __ } from '~/locale'; import { __ } from '~/locale';
import service from '../../services'; import service from '../../services';
import * as types from '../mutation_types'; import * as types from '../mutation_types';
import { activityBarViews, PERMISSION_READ_MR } from '../../constants'; import { leftSidebarViews, PERMISSION_READ_MR } from '../../constants';
export const getMergeRequestsForBranch = ( export const getMergeRequestsForBranch = (
{ commit, state, getters }, { commit, state, getters },
...@@ -187,7 +187,7 @@ export const openMergeRequest = ( ...@@ -187,7 +187,7 @@ export const openMergeRequest = (
) )
.then(mrChanges => { .then(mrChanges => {
if (mrChanges.changes.length) { if (mrChanges.changes.length) {
dispatch('updateActivityBarView', activityBarViews.review); dispatch('updateActivityBarView', leftSidebarViews.review.name);
} }
mrChanges.changes.forEach((change, ind) => { mrChanges.changes.forEach((change, ind) => {
... ...
......
import { getChangesCountForFiles, filePathMatches } from './utils'; import { getChangesCountForFiles, filePathMatches } from './utils';
import { import {
activityBarViews, leftSidebarViews,
packageJsonPath, packageJsonPath,
PERMISSION_READ_MR, PERMISSION_READ_MR,
PERMISSION_CREATE_MR, PERMISSION_CREATE_MR,
...@@ -74,9 +74,11 @@ export const getOpenFile = state => path => state.openFiles.find(f => f.path === ...@@ -74,9 +74,11 @@ export const getOpenFile = state => path => state.openFiles.find(f => f.path ===
export const lastOpenedFile = state => export const lastOpenedFile = state =>
[...state.changedFiles, ...state.stagedFiles].sort((a, b) => b.lastOpenedAt - a.lastOpenedAt)[0]; [...state.changedFiles, ...state.stagedFiles].sort((a, b) => b.lastOpenedAt - a.lastOpenedAt)[0];
export const isEditModeActive = state => state.currentActivityView === activityBarViews.edit; export const isEditModeActive = state => state.currentActivityView === leftSidebarViews.edit.name;
export const isCommitModeActive = state => state.currentActivityView === activityBarViews.commit; export const isCommitModeActive = state =>
export const isReviewModeActive = state => state.currentActivityView === activityBarViews.review; state.currentActivityView === leftSidebarViews.commit.name;
export const isReviewModeActive = state =>
state.currentActivityView === leftSidebarViews.review.name;
export const someUncommittedChanges = state => export const someUncommittedChanges = state =>
Boolean(state.changedFiles.length || state.stagedFiles.length); Boolean(state.changedFiles.length || state.stagedFiles.length);
... ...
......
...@@ -7,7 +7,7 @@ import router from '../../../ide_router'; ...@@ -7,7 +7,7 @@ import router from '../../../ide_router';
import service from '../../../services'; import service from '../../../services';
import * as types from './mutation_types'; import * as types from './mutation_types';
import consts from './constants'; import consts from './constants';
import { activityBarViews } from '../../../constants'; import { leftSidebarViews } from '../../../constants';
import eventHub from '../../../eventhub'; import eventHub from '../../../eventhub';
export const updateCommitMessage = ({ commit }, message) => { export const updateCommitMessage = ({ commit }, message) => {
...@@ -189,7 +189,7 @@ export const commitChanges = ({ commit, state, getters, dispatch, rootState, roo ...@@ -189,7 +189,7 @@ export const commitChanges = ({ commit, state, getters, dispatch, rootState, roo
throw e; throw e;
}); });
} else { } else {
dispatch('updateActivityBarView', activityBarViews.edit, { root: true }); dispatch('updateActivityBarView', leftSidebarViews.edit.name, { root: true });
dispatch('updateViewer', 'editor', { root: true }); dispatch('updateViewer', 'editor', { root: true });
if (rootGetters.activeFile) { if (rootGetters.activeFile) {
... ...
......
import { activityBarViews } from '../../../constants'; import { leftSidebarViews } from '../../../constants';
import { __ } from '~/locale'; import { __ } from '~/locale';
export const templateTypes = () => [ export const templateTypes = () => [
...@@ -22,6 +22,6 @@ export const templateTypes = () => [ ...@@ -22,6 +22,6 @@ export const templateTypes = () => [
export const showFileTemplatesBar = (_, getters, rootState) => name => export const showFileTemplatesBar = (_, getters, rootState) => name =>
getters.templateTypes.find(t => t.name === name) && getters.templateTypes.find(t => t.name === name) &&
rootState.currentActivityView === activityBarViews.edit; rootState.currentActivityView === leftSidebarViews.edit.name;
export default () => {}; export default () => {};
import { activityBarViews, viewerTypes } from '../constants'; import { leftSidebarViews, viewerTypes } from '../constants';
import { DEFAULT_THEME } from '../lib/themes'; import { DEFAULT_THEME } from '../lib/themes';
export default () => ({ export default () => ({
...@@ -21,7 +21,7 @@ export default () => ({ ...@@ -21,7 +21,7 @@ export default () => ({
entries: {}, entries: {},
viewer: viewerTypes.edit, viewer: viewerTypes.edit,
delayViewerUpdated: false, delayViewerUpdated: false,
currentActivityView: activityBarViews.edit, currentActivityView: leftSidebarViews.edit.name,
unusedSeal: true, unusedSeal: true,
fileFindVisible: false, fileFindVisible: false,
links: {}, links: {},
... ...
......
...@@ -1006,14 +1006,6 @@ pre.light-well { ...@@ -1006,14 +1006,6 @@ pre.light-well {
} }
} }
&:not(.with-pipeline-status) {
.icon-wrapper:first-of-type {
@include media-breakpoint-up(lg) {
margin-left: $gl-padding-32;
}
}
}
.ci-status-link { .ci-status-link {
display: inline-flex; display: inline-flex;
} }
... ...
......
...@@ -114,6 +114,7 @@ module Ci ...@@ -114,6 +114,7 @@ module Ci
end end
scope :eager_load_job_artifacts, -> { includes(:job_artifacts) } scope :eager_load_job_artifacts, -> { includes(:job_artifacts) }
scope :eager_load_job_artifacts_archive, -> { includes(:job_artifacts_archive) }
scope :eager_load_everything, -> do scope :eager_load_everything, -> do
includes( includes(
... ...
......
...@@ -8,7 +8,12 @@ class PipelineDetailsEntity < PipelineEntity ...@@ -8,7 +8,12 @@ class PipelineDetailsEntity < PipelineEntity
end end
expose :details do expose :details do
expose :artifacts, using: BuildArtifactEntity expose :artifacts do |pipeline, options|
rel = pipeline.artifacts
rel = rel.eager_load_job_artifacts_archive if options.fetch(:preload_job_artifacts_archive, true)
BuildArtifactEntity.represent(rel, options)
end
expose :manual_actions, using: BuildActionEntity expose :manual_actions, using: BuildActionEntity
expose :scheduled_actions, using: BuildActionEntity expose :scheduled_actions, using: BuildActionEntity
end end
... ...
......
...@@ -7,6 +7,10 @@ class PipelineSerializer < BaseSerializer ...@@ -7,6 +7,10 @@ class PipelineSerializer < BaseSerializer
# rubocop: disable CodeReuse/ActiveRecord # rubocop: disable CodeReuse/ActiveRecord
def represent(resource, opts = {}) def represent(resource, opts = {})
if resource.is_a?(ActiveRecord::Relation) if resource.is_a?(ActiveRecord::Relation)
# We don't want PipelineDetailsEntity to preload the job_artifacts_archive
# because we do it with preloaded_relations in a more optimal way
# if the given resource is a collection of multiple pipelines.
opts[:preload_job_artifacts_archive] = false
resource = resource.preload(preloaded_relations) resource = resource.preload(preloaded_relations)
end end
... ...
......
= 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, user: current_user
- is_explore_page = defined?(explore_page) && explore_page - is_explore_page = defined?(explore_page) && explore_page
= render 'shared/projects/list', projects: projects, user: current_user, explore_page: is_explore_page, pipeline_status: Feature.enabled?(:dashboard_pipeline_status, default_enabled: true) = render 'shared/projects/list', projects: projects, user: current_user, explore_page: is_explore_page
...@@ -12,9 +12,7 @@ ...@@ -12,9 +12,7 @@
- css_class += " no-description" if project.description.blank? && !show_last_commit_as_description - css_class += " no-description" if project.description.blank? && !show_last_commit_as_description
- cache_key = project_list_cache_key(project, pipeline_status: pipeline_status) - cache_key = project_list_cache_key(project, pipeline_status: pipeline_status)
- updated_tooltip = time_ago_with_tooltip(project.last_activity_date) - updated_tooltip = time_ago_with_tooltip(project.last_activity_date)
- show_pipeline_status_icon = pipeline_status && can?(current_user, :read_cross_project) && project.pipeline_status.has_status? && can?(current_user, :read_build, project)
- css_controls_class = compact_mode ? [] : ["flex-lg-row", "justify-content-lg-between"] - css_controls_class = compact_mode ? [] : ["flex-lg-row", "justify-content-lg-between"]
- css_controls_class << "with-pipeline-status" if show_pipeline_status_icon
- avatar_container_class = project.creator && use_creator_avatar ? '' : 'rect-avatar' - avatar_container_class = project.creator && use_creator_avatar ? '' : 'rect-avatar'
%li.project-row.d-flex{ class: css_class } %li.project-row.d-flex{ class: css_class }
...@@ -62,11 +60,6 @@ ...@@ -62,11 +60,6 @@
.controls.d-flex.flex-sm-column.align-items-center.align-items-sm-end.flex-wrap.flex-shrink-0.text-secondary{ class: css_controls_class.join(" ") } .controls.d-flex.flex-sm-column.align-items-center.align-items-sm-end.flex-wrap.flex-shrink-0.text-secondary{ class: css_controls_class.join(" ") }
.icon-container.d-flex.align-items-center .icon-container.d-flex.align-items-center
- if show_pipeline_status_icon
- pipeline_path = pipelines_project_commit_path(project.pipeline_status.project, project.pipeline_status.sha, ref: project.pipeline_status.ref)
%span.icon-wrapper.pipeline-status
= render 'ci/status/icon', status: project.last_pipeline.detailed_status(current_user), tooltip_placement: 'top', path: pipeline_path
= render_if_exists 'shared/projects/archived', project: project = render_if_exists 'shared/projects/archived', project: project
- if stars - if stars
= link_to project_starrers_path(project), = link_to project_starrers_path(project),
... ...
......
---
title: Remove CI status from Projects Dashboard
merge_request: 25225
author: George Thomas @thegeorgeous
type: removed
---
title: Fix N+1 queries caused by loading job artifacts archive in pipeline details
entity
merge_request: 25250
author:
type: fixed