diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-08-12 15:10:25 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-08-12 15:10:25 +0300 |
commit | 999f47e9e6da399de9dc1de404f073f7dd30af0d (patch) | |
tree | 926bf806abb6705632dc19ceb75269f40a4c9fac /app/assets/javascripts | |
parent | 20bd3b7d4ebb1d7ebef305656b156313d09a6674 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts')
13 files changed, 227 insertions, 72 deletions
diff --git a/app/assets/javascripts/lib/utils/axios_startup_calls.js b/app/assets/javascripts/lib/utils/axios_startup_calls.js index cb2e8a76c08..a047cebc8ab 100644 --- a/app/assets/javascripts/lib/utils/axios_startup_calls.js +++ b/app/assets/javascripts/lib/utils/axios_startup_calls.js @@ -34,14 +34,17 @@ const setupAxiosStartupCalls = axios => { }); // eslint-disable-next-line promise/no-nesting - return res.json().then(data => ({ - data, - status: res.status, - statusText: res.statusText, - headers: fetchHeaders, - config: req, - request: req, - })); + return res + .clone() + .json() + .then(data => ({ + data, + status: res.status, + statusText: res.statusText, + headers: fetchHeaders, + config: req, + request: req, + })); }); } diff --git a/app/assets/javascripts/monitoring/components/dashboard_actions_menu.vue b/app/assets/javascripts/monitoring/components/dashboard_actions_menu.vue index 54586c67fef..d82b8e0992e 100644 --- a/app/assets/javascripts/monitoring/components/dashboard_actions_menu.vue +++ b/app/assets/javascripts/monitoring/components/dashboard_actions_menu.vue @@ -11,6 +11,8 @@ import { GlTooltipDirective, } from '@gitlab/ui'; import CustomMetricsFormFields from '~/custom_metrics/components/custom_metrics_form_fields.vue'; +import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; +import { PANEL_NEW_PAGE } from '../router/constants'; import DuplicateDashboardModal from './duplicate_dashboard_modal.vue'; import CreateDashboardModal from './create_dashboard_modal.vue'; import { s__ } from '~/locale'; @@ -36,6 +38,7 @@ export default { GlTooltip: GlTooltipDirective, TrackEvent: TrackEventDirective, }, + mixins: [glFeatureFlagsMixin()], props: { addingMetricsAvailable: { type: Boolean, @@ -56,6 +59,10 @@ export default { type: String, required: true, }, + isOotbDashboard: { + type: Boolean, + required: true, + }, }, data() { return { customMetricsFormIsValid: null }; @@ -72,15 +79,22 @@ export default { }, isMenuItemEnabled() { return { + addPanel: !this.isOotbDashboard, createDashboard: Boolean(this.projectPath), editDashboard: this.selectedDashboard?.can_edit, }; }, isMenuItemShown() { return { + addPanel: this.glFeatures.metricsDashboardNewPanelPage, duplicateDashboard: this.isOutOfTheBoxDashboard, }; }, + newPanelPageLocation() { + // Retains params/query if any + const { params, query } = this.$route ?? {}; + return { name: PANEL_NEW_PAGE, params, query }; + }, }, methods: { ...mapActions('monitoringDashboard', ['toggleStarredValue']), @@ -117,7 +131,9 @@ export default { starDashboard: s__('Metrics|Star dashboard'), unstarDashboard: s__('Metrics|Unstar dashboard'), addMetric: s__('Metrics|Add metric'), - editDashboardInfo: s__('Metrics|Duplicate this dashboard to edit dashboard YAML'), + addPanel: s__('Metrics|Add panel'), + addPanelInfo: s__('Metrics|Duplicate this dashboard to add panel or edit dashboard YAML.'), + editDashboardInfo: s__('Metrics|Duplicate this dashboard to add panel or edit dashboard YAML.'), editDashboard: s__('Metrics|Edit dashboard YAML'), createDashboard: s__('Metrics|Create new dashboard'), }, @@ -176,6 +192,32 @@ export default { </gl-modal> </template> + <template v-if="isMenuItemShown.addPanel"> + <gl-new-dropdown-item + v-if="isMenuItemEnabled.addPanel" + data-testid="add-panel-item-enabled" + :to="newPanelPageLocation" + > + {{ $options.i18n.addPanel }} + </gl-new-dropdown-item> + + <!-- + wrapper for tooltip as button can be `disabled` + https://bootstrap-vue.org/docs/components/tooltip#disabled-elements + --> + <div v-else v-gl-tooltip :title="$options.i18n.addPanelInfo"> + <gl-new-dropdown-item + :alt="$options.i18n.addPanelInfo" + :to="newPanelPageLocation" + data-testid="add-panel-item-disabled" + disabled + class="gl-cursor-not-allowed" + > + <span class="gl-text-gray-400">{{ $options.i18n.addPanel }}</span> + </gl-new-dropdown-item> + </div> + </template> + <gl-new-dropdown-item v-if="isMenuItemEnabled.editDashboard" :href="selectedDashboard ? selectedDashboard.project_blob_path : null" diff --git a/app/assets/javascripts/monitoring/components/dashboard_header.vue b/app/assets/javascripts/monitoring/components/dashboard_header.vue index 1c921548ce7..1048e72a431 100644 --- a/app/assets/javascripts/monitoring/components/dashboard_header.vue +++ b/app/assets/javascripts/monitoring/components/dashboard_header.vue @@ -118,6 +118,9 @@ export default { shouldShowSettingsButton() { return this.canAccessOperationsSettings && this.operationsSettingsPath; }, + isOOTBDashboard() { + return this.selectedDashboard?.out_of_the_box_dashboard ?? false; + }, }, methods: { ...mapActions('monitoringDashboard', ['filterEnvironments']), @@ -266,6 +269,7 @@ export default { :custom-metrics-path="customMetricsPath" :validate-query-path="validateQueryPath" :default-branch="defaultBranch" + :is-ootb-dashboard="isOOTBDashboard" /> </div> diff --git a/app/assets/javascripts/monitoring/queries/getAnnotations.query.graphql b/app/assets/javascripts/monitoring/queries/getAnnotations.query.graphql index 27b49860b8a..32b982ff195 100644 --- a/app/assets/javascripts/monitoring/queries/getAnnotations.query.graphql +++ b/app/assets/javascripts/monitoring/queries/getAnnotations.query.graphql @@ -5,6 +5,7 @@ query getAnnotations( $startingFrom: Time! ) { project(fullPath: $projectPath) { + id environments(name: $environmentName) { nodes { id diff --git a/app/assets/javascripts/monitoring/queries/getEnvironments.query.graphql b/app/assets/javascripts/monitoring/queries/getEnvironments.query.graphql index 17cd1b2c342..48d0a780fc7 100644 --- a/app/assets/javascripts/monitoring/queries/getEnvironments.query.graphql +++ b/app/assets/javascripts/monitoring/queries/getEnvironments.query.graphql @@ -1,5 +1,6 @@ query getEnvironments($projectPath: ID!, $search: String, $states: [String!]) { project(fullPath: $projectPath) { + id data: environments(search: $search, states: $states) { environments: nodes { name diff --git a/app/assets/javascripts/monitoring/router/routes.js b/app/assets/javascripts/monitoring/router/routes.js index 8092a5b7c0b..cc43fd8622a 100644 --- a/app/assets/javascripts/monitoring/router/routes.js +++ b/app/assets/javascripts/monitoring/router/routes.js @@ -13,12 +13,12 @@ import { DASHBOARD_PAGE, PANEL_NEW_PAGE } from './constants'; export default [ { name: PANEL_NEW_PAGE, - path: '/:dashboard(.*)?/panel/new', + path: '/:dashboard(.+)?/panel/new', component: PanelNewPage, }, { name: DASHBOARD_PAGE, - path: '/:dashboard(.*)?', + path: '/:dashboard(.+)?', component: DashboardPage, }, ]; diff --git a/app/assets/javascripts/notes/components/notes_app.vue b/app/assets/javascripts/notes/components/notes_app.vue index faa6006945d..262c0b53e79 100644 --- a/app/assets/javascripts/notes/components/notes_app.vue +++ b/app/assets/javascripts/notes/components/notes_app.vue @@ -136,6 +136,8 @@ export default { } window.addEventListener('hashchange', this.handleHashChanged); + + eventHub.$on('notesApp.updateIssuableConfidentiality', this.setConfidentiality); }, updated() { this.$nextTick(() => { @@ -146,6 +148,7 @@ export default { beforeDestroy() { this.stopPolling(); window.removeEventListener('hashchange', this.handleHashChanged); + eventHub.$off('notesApp.updateIssuableConfidentiality', this.setConfidentiality); }, methods: { ...mapActions([ @@ -164,6 +167,7 @@ export default { 'startTaskList', 'convertToDiscussion', 'stopPolling', + 'setConfidentiality', ]), discussionIsIndividualNoteAndNotConverted(discussion) { return discussion.individual_note && !this.convertedDisscussionIds.includes(discussion.id); diff --git a/app/assets/javascripts/notes/stores/actions.js b/app/assets/javascripts/notes/stores/actions.js index ac57fcf2ea5..3f4da32ec35 100644 --- a/app/assets/javascripts/notes/stores/actions.js +++ b/app/assets/javascripts/notes/stores/actions.js @@ -21,29 +21,6 @@ import Api from '~/api'; let eTagPoll; -export const updateConfidentialityOnIssue = ({ commit, getters }, { confidential, fullPath }) => { - const { iid } = getters.getNoteableData; - - return utils.gqClient - .mutate({ - mutation: updateIssueConfidentialMutation, - variables: { - input: { - projectPath: fullPath, - iid: String(iid), - confidential, - }, - }, - }) - .then(({ data }) => { - const { - issueSetConfidential: { issue }, - } = data; - - commit(types.SET_ISSUE_CONFIDENTIAL, issue.confidential); - }); -}; - export const updateLockedAttribute = ({ commit, getters }, { locked, fullPath }) => { const { iid, targetType } = getters.getNoteableData; @@ -712,3 +689,29 @@ export const updateAssignees = ({ commit }, assignees) => { export const updateDiscussionPosition = ({ commit }, updatedPosition) => { commit(types.UPDATE_DISCUSSION_POSITION, updatedPosition); }; + +export const updateConfidentialityOnIssuable = ( + { getters, commit }, + { confidential, fullPath }, +) => { + const { iid } = getters.getNoteableData; + + return utils.gqClient + .mutate({ + mutation: updateIssueConfidentialMutation, + variables: { + input: { + projectPath: fullPath, + iid: String(iid), + confidential, + }, + }, + }) + .then(({ data }) => { + const { + issueSetConfidential: { issue }, + } = data; + + setConfidentiality({ commit }, issue.confidential); + }); +}; diff --git a/app/assets/javascripts/pages/projects/commit/show/index.js b/app/assets/javascripts/pages/projects/commit/show/index.js index 0eb6f231839..a245af72d93 100644 --- a/app/assets/javascripts/pages/projects/commit/show/index.js +++ b/app/assets/javascripts/pages/projects/commit/show/index.js @@ -7,23 +7,47 @@ import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation'; import MiniPipelineGraph from '~/mini_pipeline_graph_dropdown'; import initNotes from '~/init_notes'; import initChangesDropdown from '~/init_changes_dropdown'; -import initDiffNotes from '~/diff_notes/diff_notes_bundle'; import { fetchCommitMergeRequests } from '~/commit_merge_requests'; import '~/sourcegraph/load'; +import { handleLocationHash } from '~/lib/utils/common_utils'; +import axios from '~/lib/utils/axios_utils'; +import syntaxHighlight from '~/syntax_highlight'; +import flash from '~/flash'; +import { __ } from '~/locale'; document.addEventListener('DOMContentLoaded', () => { const hasPerfBar = document.querySelector('.with-performance-bar'); const performanceHeight = hasPerfBar ? 35 : 0; - new Diff(); - new ZenMode(); - new ShortcutsNavigation(); - new MiniPipelineGraph({ - container: '.js-commit-pipeline-graph', - }).bindEvents(); - initNotes(); - initChangesDropdown(document.querySelector('.navbar-gitlab').offsetHeight + performanceHeight); - // eslint-disable-next-line no-jquery/no-load - $('.commit-info.branches').load(document.querySelector('.js-commit-box').dataset.commitPath); - fetchCommitMergeRequests(); - initDiffNotes(); + const filesContainer = $('.js-diffs-batch'); + const initAfterPageLoad = () => { + new Diff(); + new ZenMode(); + new ShortcutsNavigation(); + new MiniPipelineGraph({ + container: '.js-commit-pipeline-graph', + }).bindEvents(); + initNotes(); + initChangesDropdown(document.querySelector('.navbar-gitlab').offsetHeight + performanceHeight); + // eslint-disable-next-line no-jquery/no-load + $('.commit-info.branches').load(document.querySelector('.js-commit-box').dataset.commitPath); + fetchCommitMergeRequests(); + }; + + if (filesContainer.length) { + const batchPath = filesContainer.data('diffFilesPath'); + + axios + .get(batchPath) + .then(({ data }) => { + filesContainer.html($(data.html)); + syntaxHighlight(filesContainer); + handleLocationHash(); + initAfterPageLoad(); + }) + .catch(() => { + flash(__('An error occurred while retrieving diff files')); + }); + } else { + initAfterPageLoad(); + } }); diff --git a/app/assets/javascripts/repository/components/tree_content.vue b/app/assets/javascripts/repository/components/tree_content.vue index 721cc6787dc..702df42d655 100644 --- a/app/assets/javascripts/repository/components/tree_content.vue +++ b/app/assets/javascripts/repository/components/tree_content.vue @@ -1,4 +1,5 @@ <script> +import { GlButton } from '@gitlab/ui'; import createFlash from '~/flash'; import { __ } from '../../locale'; import FileTable from './table/index.vue'; @@ -8,12 +9,15 @@ import projectPathQuery from '../queries/project_path.query.graphql'; import FilePreview from './preview/index.vue'; import { readmeFile } from '../utils/readme'; +const LIMIT = 1000; const PAGE_SIZE = 100; +export const INITIAL_FETCH_COUNT = LIMIT / PAGE_SIZE; export default { components: { FileTable, FilePreview, + GlButton, }, mixins: [getRefMixin], apollo: { @@ -43,12 +47,19 @@ export default { blobs: [], }, isLoadingFiles: false, + isOverLimit: false, + clickedShowMore: false, + pageSize: PAGE_SIZE, + fetchCounter: 0, }; }, computed: { readme() { return readmeFile(this.entries.blobs); }, + hasShowMore() { + return !this.clickedShowMore && this.fetchCounter === INITIAL_FETCH_COUNT; + }, }, watch: { @@ -76,7 +87,7 @@ export default { ref: this.ref, path: this.path || '/', nextPageCursor: this.nextPageCursor, - pageSize: PAGE_SIZE, + pageSize: this.pageSize, }, }) .then(({ data }) => { @@ -96,7 +107,11 @@ export default { if (pageInfo?.hasNextPage) { this.nextPageCursor = pageInfo.endCursor; - this.fetchFiles(); + this.fetchCounter += 1; + if (this.fetchCounter < INITIAL_FETCH_COUNT || this.clickedShowMore) { + this.fetchFiles(); + this.clickedShowMore = false; + } } }) .catch(error => { @@ -112,6 +127,10 @@ export default { .concat(data.trees.pageInfo, data.submodules.pageInfo, data.blobs.pageInfo) .find(({ hasNextPage }) => hasNextPage); }, + showMore() { + this.clickedShowMore = true; + this.fetchFiles(); + }, }, }; </script> @@ -124,6 +143,19 @@ export default { :is-loading="isLoadingFiles" :loading-path="loadingPath" /> + <div + v-if="hasShowMore" + class="gl-border-1 gl-border-gray-100 gl-rounded-base gl-border-t-none gl-border-b-solid gl-border-l-solid gl-border-r-solid gl-rounded-top-right-none gl-rounded-top-left-none gl-mt-n1" + > + <gl-button + variant="link" + class="gl-display-flex gl-w-full gl-py-4!" + :loading="isLoadingFiles" + @click="showMore" + > + {{ s__('ProjectFileTree|Show more') }} + </gl-button> + </div> <file-preview v-if="readme" :blob="readme" /> </div> </template> diff --git a/app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue b/app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue index 7dbeb3055c6..c6f7d5e44ad 100644 --- a/app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue +++ b/app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue @@ -1,6 +1,6 @@ <script> -import { mapState, mapActions } from 'vuex'; -import { __ } from '~/locale'; +import { mapState } from 'vuex'; +import { __, sprintf } from '~/locale'; import tooltip from '~/vue_shared/directives/tooltip'; import Icon from '~/vue_shared/components/icon.vue'; import eventHub from '~/sidebar/event_hub'; @@ -23,9 +23,10 @@ export default { required: true, type: Boolean, }, - service: { - required: true, - type: Object, + issuableType: { + required: false, + type: String, + default: 'issue', }, }, data() { @@ -34,13 +35,25 @@ export default { }; }, computed: { - ...mapState({ confidential: ({ noteableData }) => noteableData.confidential }), + ...mapState({ + confidential: ({ noteableData, confidential }) => { + if (noteableData) { + return noteableData.confidential; + } + return Boolean(confidential); + }, + }), confidentialityIcon() { return this.confidential ? 'eye-slash' : 'eye'; }, tooltipLabel() { return this.confidential ? __('Confidential') : __('Not confidential'); }, + confidentialText() { + return sprintf(__('This %{issuableType} is confidential'), { + issuableType: this.issuableType, + }); + }, }, created() { eventHub.$on('closeConfidentialityForm', this.toggleForm); @@ -49,7 +62,6 @@ export default { eventHub.$off('closeConfidentialityForm', this.toggleForm); }, methods: { - ...mapActions(['setConfidentiality']), toggleForm() { this.edit = !this.edit; }, @@ -86,7 +98,12 @@ export default { > </div> <div class="value sidebar-item-value hide-collapsed"> - <edit-form v-if="edit" :is-confidential="confidential" :full-path="fullPath" /> + <edit-form + v-if="edit" + :confidential="confidential" + :full-path="fullPath" + :issuable-type="issuableType" + /> <div v-if="!confidential" class="no-value sidebar-item-value" data-testid="not-confidential"> <icon :size="16" name="eye" aria-hidden="true" class="sidebar-item-icon inline" /> {{ __('Not confidential') }} @@ -98,7 +115,7 @@ export default { aria-hidden="true" class="sidebar-item-icon inline is-active" /> - {{ __('This issue is confidential') }} + {{ confidentialText }} </div> </div> </div> diff --git a/app/assets/javascripts/sidebar/components/confidential/edit_form.vue b/app/assets/javascripts/sidebar/components/confidential/edit_form.vue index 9dd4f04acdb..6dad68800f9 100644 --- a/app/assets/javascripts/sidebar/components/confidential/edit_form.vue +++ b/app/assets/javascripts/sidebar/components/confidential/edit_form.vue @@ -1,13 +1,13 @@ <script> import editFormButtons from './edit_form_buttons.vue'; -import { s__ } from '../../../locale'; +import { __, sprintf } from '../../../locale'; export default { components: { editFormButtons, }, props: { - isConfidential: { + confidential: { required: true, type: Boolean, }, @@ -15,16 +15,32 @@ export default { required: true, type: String, }, + issuableType: { + required: true, + type: String, + }, }, computed: { confidentialityOnWarning() { - return s__( - 'confidentiality|You are going to turn on the confidentiality. This means that only team members with <strong>at least Reporter access</strong> are able to see and leave comments on the issue.', + const accessLevel = __('at least Reporter access'); + + return sprintf( + __( + 'You are going to turn on the confidentiality. This means that only team members with %{accessLevel} are able to see and leave comments on the %{issuableType}.', + ), + { issuableType: this.issuableType, accessLevel: `<strong>${accessLevel}</strong>` }, + false, ); }, confidentialityOffWarning() { - return s__( - 'confidentiality|You are going to turn off the confidentiality. This means <strong>everyone</strong> will be able to see and leave a comment on this issue.', + const accessLevel = __('everyone'); + + return sprintf( + __( + 'You are going to turn off the confidentiality. This means %{accessLevel} will be able to see and leave a comment on this %{issuableType}.', + ), + { issuableType: this.issuableType, accessLevel: `<strong>${accessLevel}</strong>` }, + false, ); }, }, @@ -35,9 +51,9 @@ export default { <div class="dropdown show"> <div class="dropdown-menu sidebar-item-warning-message"> <div> - <p v-if="!isConfidential" v-html="confidentialityOnWarning"></p> + <p v-if="!confidential" v-html="confidentialityOnWarning"></p> <p v-else v-html="confidentialityOffWarning"></p> - <edit-form-buttons :full-path="fullPath" /> + <edit-form-buttons :full-path="fullPath" :confidential="confidential" /> </div> </div> </div> diff --git a/app/assets/javascripts/sidebar/components/confidential/edit_form_buttons.vue b/app/assets/javascripts/sidebar/components/confidential/edit_form_buttons.vue index ef3e0ccfa86..be273a616a0 100644 --- a/app/assets/javascripts/sidebar/components/confidential/edit_form_buttons.vue +++ b/app/assets/javascripts/sidebar/components/confidential/edit_form_buttons.vue @@ -1,7 +1,7 @@ <script> import $ from 'jquery'; import { GlLoadingIcon } from '@gitlab/ui'; -import { mapActions, mapState } from 'vuex'; +import { mapActions } from 'vuex'; import { __ } from '~/locale'; import Flash from '~/flash'; import eventHub from '../../event_hub'; @@ -15,6 +15,10 @@ export default { required: true, type: String, }, + confidential: { + required: true, + type: Boolean, + }, }, data() { return { @@ -22,7 +26,6 @@ export default { }; }, computed: { - ...mapState({ confidential: ({ noteableData }) => noteableData.confidential }), toggleButtonText() { if (this.isLoading) { return __('Applying'); @@ -32,7 +35,7 @@ export default { }, }, methods: { - ...mapActions(['updateConfidentialityOnIssue']), + ...mapActions(['updateConfidentialityOnIssuable']), closeForm() { eventHub.$emit('closeConfidentialityForm'); $(this.$el).trigger('hidden.gl.dropdown'); @@ -41,9 +44,14 @@ export default { this.isLoading = true; const confidential = !this.confidential; - this.updateConfidentialityOnIssue({ confidential, fullPath: this.fullPath }) - .catch(() => { - Flash(__('Something went wrong trying to change the confidentiality of this issue')); + this.updateConfidentialityOnIssuable({ confidential, fullPath: this.fullPath }) + .then(() => { + eventHub.$emit('updateIssuableConfidentiality', confidential); + }) + .catch(err => { + Flash( + err || __('Something went wrong trying to change the confidentiality of this issue'), + ); }) .finally(() => { this.closeForm(); |