diff options
author | Dennis Tang <dtang@gitlab.com> | 2018-05-25 23:56:17 +0200 |
---|---|---|
committer | Dennis Tang <dtang@gitlab.com> | 2018-05-25 23:56:17 +0200 |
commit | 95a63a881673533e3fd44243297d1a81e19396b6 (patch) | |
tree | 9a3190b813e2d599043394b30afaa5a5c8f8e565 /app/assets | |
parent | 48e46f959716c8915f5b59d1314b5e5781f3cd8d (diff) | |
parent | 50c8ed2bf498c69d3d52ba1451274e3fbf438429 (diff) | |
download | gitlab-ce-95a63a881673533e3fd44243297d1a81e19396b6.tar.gz |
Merge remote-tracking branch 'origin/master' into 38759-fetch-available-parameters-directly-from-gke-when-creating-a-cluster
Diffstat (limited to 'app/assets')
246 files changed, 2108 insertions, 1806 deletions
diff --git a/app/assets/javascripts/api.js b/app/assets/javascripts/api.js index 8ad3d18b302..ce1069276ab 100644 --- a/app/assets/javascripts/api.js +++ b/app/assets/javascripts/api.js @@ -21,8 +21,11 @@ const Api = { issuableTemplatePath: '/:namespace_path/:project_path/templates/:type/:key', usersPath: '/api/:version/users.json', commitPath: '/api/:version/projects/:id/repository/commits', + commitPipelinesPath: '/:project_id/commit/:sha/pipelines', branchSinglePath: '/api/:version/projects/:id/repository/branches/:branch', createBranchPath: '/api/:version/projects/:id/repository/branches', + pipelinesPath: '/api/:version/projects/:id/pipelines', + pipelineJobsPath: '/api/:version/projects/:id/pipelines/:pipeline_id/jobs', group(groupId, callback) { const url = Api.buildUrl(Api.groupPath).replace(':id', groupId); @@ -164,6 +167,19 @@ const Api = { }); }, + commitPipelines(projectId, sha) { + const encodedProjectId = projectId + .split('/') + .map(fragment => encodeURIComponent(fragment)) + .join('/'); + + const url = Api.buildUrl(Api.commitPipelinesPath) + .replace(':project_id', encodedProjectId) + .replace(':sha', encodeURIComponent(sha)); + + return axios.get(url); + }, + branchSingle(id, branch) { const url = Api.buildUrl(Api.branchSinglePath) .replace(':id', encodeURIComponent(id)) @@ -222,6 +238,20 @@ const Api = { }); }, + pipelines(projectPath, params = {}) { + const url = Api.buildUrl(this.pipelinesPath).replace(':id', encodeURIComponent(projectPath)); + + return axios.get(url, { params }); + }, + + pipelineJobs(projectPath, pipelineId, params = {}) { + const url = Api.buildUrl(this.pipelineJobsPath) + .replace(':id', encodeURIComponent(projectPath)) + .replace(':pipeline_id', pipelineId); + + return axios.get(url, { params }); + }, + buildUrl(url) { let urlRoot = ''; if (gon.relative_url_root != null) { diff --git a/app/assets/javascripts/awards_handler.js b/app/assets/javascripts/awards_handler.js index 976d32abe9b..eb0f06efab4 100644 --- a/app/assets/javascripts/awards_handler.js +++ b/app/assets/javascripts/awards_handler.js @@ -345,7 +345,7 @@ class AwardsHandler { counter.text(counterNumber - 1); this.removeYouFromUserList($emojiButton); } else if (emoji === 'thumbsup' || emoji === 'thumbsdown') { - $emojiButton.tooltip('destroy'); + $emojiButton.tooltip('dispose'); counter.text('0'); this.removeYouFromUserList($emojiButton); if ($emojiButton.parents('.note').length) { @@ -358,7 +358,7 @@ class AwardsHandler { } removeEmoji($emojiButton) { - $emojiButton.tooltip('destroy'); + $emojiButton.tooltip('dispose'); $emojiButton.remove(); const $votesBlock = this.getVotesBlock(); if ($votesBlock.find('.js-emoji-btn').length === 0) { @@ -392,7 +392,7 @@ class AwardsHandler { .removeAttr('data-title') .removeAttr('data-original-title') .attr('title', this.toSentence(authors)) - .tooltip('fixTitle'); + .tooltip('_fixTitle'); } addYouToUserList(votesBlock, emoji) { @@ -405,7 +405,7 @@ class AwardsHandler { users.unshift('You'); return awardBlock .attr('title', this.toSentence(users)) - .tooltip('fixTitle'); + .tooltip('_fixTitle'); } createAwardButtonForVotesBlock(votesBlock, emojiName) { diff --git a/app/assets/javascripts/badges/components/badge.vue b/app/assets/javascripts/badges/components/badge.vue index 6e6cb31e3ac..d0f60e1d4cb 100644 --- a/app/assets/javascripts/badges/components/badge.vue +++ b/app/assets/javascripts/badges/components/badge.vue @@ -89,7 +89,7 @@ export default { v-show="hasError" class="btn-group" > - <div class="btn btn-default btn-xs disabled"> + <div class="btn btn-default btn-sm disabled"> <icon class="prepend-left-8 append-right-8" name="doc_image" @@ -98,7 +98,7 @@ export default { /> </div> <div - class="btn btn-default btn-xs disabled" + class="btn btn-default btn-sm disabled" > <span class="prepend-left-8 append-right-8">{{ s__('Badges|No badge image') }}</span> </div> @@ -106,7 +106,7 @@ export default { <button v-show="hasError" - class="btn btn-transparent btn-xs text-primary" + class="btn btn-transparent btn-sm text-primary" type="button" v-tooltip :title="s__('Badges|Reload badge image')" diff --git a/app/assets/javascripts/badges/components/badge_list.vue b/app/assets/javascripts/badges/components/badge_list.vue index ca7197e1e0f..268968b63b3 100644 --- a/app/assets/javascripts/badges/components/badge_list.vue +++ b/app/assets/javascripts/badges/components/badge_list.vue @@ -23,8 +23,8 @@ export default { </script> <template> - <div class="panel panel-default"> - <div class="panel-heading"> + <div class="card"> + <div class="card-header"> {{ s__('Badges|Your badges') }} <span v-show="!isLoading" @@ -33,19 +33,19 @@ export default { </div> <loading-icon v-show="isLoading" - class="panel-body" + class="card-body" size="2" /> <div v-if="hasNoBadges" - class="panel-body" + class="card-body" > <span v-if="isGroupBadge">{{ s__('Badges|This group has no badges') }}</span> <span v-else>{{ s__('Badges|This project has no badges') }}</span> </div> <div v-else - class="panel-body" + class="card-body" > <badge-list-row v-for="badge in badges" diff --git a/app/assets/javascripts/behaviors/copy_to_clipboard.js b/app/assets/javascripts/behaviors/copy_to_clipboard.js index e2a73a1797c..75834ba351d 100644 --- a/app/assets/javascripts/behaviors/copy_to_clipboard.js +++ b/app/assets/javascripts/behaviors/copy_to_clipboard.js @@ -8,10 +8,10 @@ function showTooltip(target, title) { if (!$target.data('hideTooltip')) { $target .attr('title', title) - .tooltip('fixTitle') + .tooltip('_fixTitle') .tooltip('show') .attr('title', originalTitle) - .tooltip('fixTitle'); + .tooltip('_fixTitle'); } } diff --git a/app/assets/javascripts/behaviors/quick_submit.js b/app/assets/javascripts/behaviors/quick_submit.js index 3ec932bdb73..b6e2781773c 100644 --- a/app/assets/javascripts/behaviors/quick_submit.js +++ b/app/assets/javascripts/behaviors/quick_submit.js @@ -69,7 +69,7 @@ $(document).on('keyup.quick_submit', '.js-quick-submit input[type=submit], .js-q $this.tooltip({ container: 'body', html: 'true', - placement: 'auto top', + placement: 'top', title, trigger: 'manual', }); diff --git a/app/assets/javascripts/behaviors/requires_input.js b/app/assets/javascripts/behaviors/requires_input.js index ffff4ddb71a..a8b6dbf0948 100644 --- a/app/assets/javascripts/behaviors/requires_input.js +++ b/app/assets/javascripts/behaviors/requires_input.js @@ -42,9 +42,9 @@ $.fn.requiresInput = function requiresInput() { function hideOrShowHelpBlock(form) { const selected = $('.js-select-namespace option:selected'); if (selected.length && selected.data('optionsParent') === 'groups') { - form.find('.help-block').hide(); + form.find('.form-text.text-muted').hide(); } else if (selected.length) { - form.find('.help-block').show(); + form.find('.form-text.text-muted').show(); } } diff --git a/app/assets/javascripts/blob/balsamiq/balsamiq_viewer.js b/app/assets/javascripts/blob/balsamiq/balsamiq_viewer.js index c17877a276d..766039404ce 100644 --- a/app/assets/javascripts/blob/balsamiq/balsamiq_viewer.js +++ b/app/assets/javascripts/blob/balsamiq/balsamiq_viewer.js @@ -2,9 +2,9 @@ import sqljs from 'sql.js'; import { template as _template } from 'underscore'; const PREVIEW_TEMPLATE = _template(` - <div class="panel panel-default"> - <div class="panel-heading"><%- name %></div> - <div class="panel-body"> + <div class="card"> + <div class="card-header"><%- name %></div> + <div class="card-body"> <img class="img-thumbnail" src="data:image/png;base64,<%- image %>"/> </div> </div> diff --git a/app/assets/javascripts/blob/sketch/index.js b/app/assets/javascripts/blob/sketch/index.js index 0799991aa40..13318c58006 100644 --- a/app/assets/javascripts/blob/sketch/index.js +++ b/app/assets/javascripts/blob/sketch/index.js @@ -44,7 +44,7 @@ export default class SketchLoader { previewLink.href = previewUrl; previewLink.target = '_blank'; previewImage.src = previewUrl; - previewImage.className = 'img-responsive'; + previewImage.className = 'img-fluid'; previewLink.appendChild(previewImage); this.container.appendChild(previewLink); diff --git a/app/assets/javascripts/blob/viewer/index.js b/app/assets/javascripts/blob/viewer/index.js index 137e1f5a099..f61c0be9230 100644 --- a/app/assets/javascripts/blob/viewer/index.js +++ b/app/assets/javascripts/blob/viewer/index.js @@ -116,7 +116,7 @@ export default class BlobViewer { this.copySourceBtn.classList.add('disabled'); } - $(this.copySourceBtn).tooltip('fixTitle'); + $(this.copySourceBtn).tooltip('_fixTitle'); } switchToViewer(name) { diff --git a/app/assets/javascripts/boards/components/board_card.vue b/app/assets/javascripts/boards/components/board_card.vue index 84885ca9306..33e3369b971 100644 --- a/app/assets/javascripts/boards/components/board_card.vue +++ b/app/assets/javascripts/boards/components/board_card.vue @@ -77,7 +77,7 @@ export default { <template> <li - class="card" + class="board-card" :class="{ 'user-can-drag': !disabled && issue.id, 'is-disabled': disabled || !issue.id, diff --git a/app/assets/javascripts/boards/components/board_new_issue.vue b/app/assets/javascripts/boards/components/board_new_issue.vue index 8d84c1735b8..e8dfd95f7ae 100644 --- a/app/assets/javascripts/boards/components/board_new_issue.vue +++ b/app/assets/javascripts/boards/components/board_new_issue.vue @@ -92,7 +92,7 @@ export default { <template> <div class="board-new-issue-form"> - <div class="card"> + <div class="board-card"> <form @submit="submit($event)"> <div class="flash-container" @@ -122,7 +122,7 @@ export default { /> <div class="clearfix prepend-top-10"> <button - class="btn btn-success pull-left" + class="btn btn-success float-left" type="submit" :disabled="disabled" ref="submit-button" @@ -130,7 +130,7 @@ export default { Submit issue </button> <button - class="btn btn-default pull-right" + class="btn btn-default float-right" type="button" @click="cancel" > diff --git a/app/assets/javascripts/boards/components/issue_card_inner.js b/app/assets/javascripts/boards/components/issue_card_inner.js index 84fe9b1288a..dcc07810d01 100644 --- a/app/assets/javascripts/boards/components/issue_card_inner.js +++ b/app/assets/javascripts/boards/components/issue_card_inner.js @@ -135,8 +135,8 @@ gl.issueBoards.IssueCardInner = Vue.extend({ }, template: ` <div> - <div class="card-header"> - <h4 class="card-title"> + <div class="board-card-header"> + <h4 class="board-card-title"> <i class="fa fa-eye-slash confidential-icon" v-if="issue.confidential" @@ -147,13 +147,13 @@ gl.issueBoards.IssueCardInner = Vue.extend({ :href="issue.path" :title="issue.title">{{ issue.title }}</a> <span - class="card-number" + class="board-card-number" v-if="issueId" > {{ issue.referencePath }} </span> </h4> - <div class="card-assignee"> + <div class="board-card-assignee"> <user-avatar-link v-for="(assignee, index) in issue.assignees" :key="assignee.id" @@ -175,11 +175,11 @@ gl.issueBoards.IssueCardInner = Vue.extend({ </div> </div> <div - class="card-footer" + class="board-card-footer" v-if="showLabelFooter" > <button - class="label color-label has-tooltip" + class="badge color-label has-tooltip" v-for="label in issue.labels" type="button" v-if="showLabel(label)" diff --git a/app/assets/javascripts/boards/components/modal/empty_state.js b/app/assets/javascripts/boards/components/modal/empty_state.js index 9e37f95cdd6..eb8a66975ee 100644 --- a/app/assets/javascripts/boards/components/modal/empty_state.js +++ b/app/assets/javascripts/boards/components/modal/empty_state.js @@ -41,10 +41,10 @@ gl.issueBoards.ModalEmptyState = Vue.extend({ template: ` <section class="empty-state"> <div class="row"> - <div class="col-xs-12 col-sm-6 col-sm-push-6"> + <div class="col-xs-12 col-sm-6 order-sm-last"> <aside class="svg-content"><img :src="emptyStateSvg"/></aside> </div> - <div class="col-xs-12 col-sm-6 col-sm-pull-6"> + <div class="col-xs-12 col-sm-6 order-sm-first"> <div class="text-content"> <h4>{{ contents.title }}</h4> <p v-html="contents.content"></p> diff --git a/app/assets/javascripts/boards/components/modal/footer.js b/app/assets/javascripts/boards/components/modal/footer.js index 9735e0ddacc..11bb3e98334 100644 --- a/app/assets/javascripts/boards/components/modal/footer.js +++ b/app/assets/javascripts/boards/components/modal/footer.js @@ -58,7 +58,7 @@ gl.issueBoards.ModalFooter = Vue.extend({ template: ` <footer class="form-actions add-issues-footer"> - <div class="pull-left"> + <div class="float-left"> <button class="btn btn-success" type="button" @@ -72,7 +72,7 @@ gl.issueBoards.ModalFooter = Vue.extend({ <lists-dropdown></lists-dropdown> </div> <button - class="btn btn-default pull-right" + class="btn btn-default float-right" type="button" @click="toggleModal(false)"> Cancel diff --git a/app/assets/javascripts/boards/components/modal/list.js b/app/assets/javascripts/boards/components/modal/list.js index 6b04a6c7a6c..6c662432037 100644 --- a/app/assets/javascripts/boards/components/modal/list.js +++ b/app/assets/javascripts/boards/components/modal/list.js @@ -133,9 +133,9 @@ gl.issueBoards.ModalList = Vue.extend({ <div v-for="issue in group" v-if="showIssue(issue)" - class="card-parent"> + class="board-card-parent"> <div - class="card" + class="board-card" :class="{ 'is-active': issue.selected }" @click="toggleIssue($event, issue)"> <issue-card-inner diff --git a/app/assets/javascripts/boards/components/modal/tabs.js b/app/assets/javascripts/boards/components/modal/tabs.js index b6465a88e5e..9d331de8e22 100644 --- a/app/assets/javascripts/boards/components/modal/tabs.js +++ b/app/assets/javascripts/boards/components/modal/tabs.js @@ -24,7 +24,7 @@ gl.issueBoards.ModalTabs = Vue.extend({ role="button" @click.prevent="changeTab('all')"> Open issues - <span class="badge"> + <span class="badge badge-pill"> {{ issuesCount }} </span> </a> @@ -35,7 +35,7 @@ gl.issueBoards.ModalTabs = Vue.extend({ role="button" @click.prevent="changeTab('selected')"> Selected issues - <span class="badge"> + <span class="badge badge-pill"> {{ selectedCount }} </span> </a> diff --git a/app/assets/javascripts/boards/index.js b/app/assets/javascripts/boards/index.js index a6f8681cfac..29ab13b8e0b 100644 --- a/app/assets/javascripts/boards/index.js +++ b/app/assets/javascripts/boards/index.js @@ -214,7 +214,7 @@ export default () => { if (this.disabled) { $tooltip.tooltip(); } else { - $tooltip.tooltip('destroy'); + $tooltip.tooltip('dispose'); } }); }, diff --git a/app/assets/javascripts/ci_variable_list/ci_variable_list.js b/app/assets/javascripts/ci_variable_list/ci_variable_list.js index e177a3bfdc7..47efb3a8cee 100644 --- a/app/assets/javascripts/ci_variable_list/ci_variable_list.js +++ b/app/assets/javascripts/ci_variable_list/ci_variable_list.js @@ -141,6 +141,11 @@ export default class VariableList { $rowClone.find(entry.selector).val(entry.default); }); + // Close any dropdowns + $rowClone.find('.dropdown-menu.show').each((index, $dropdown) => { + $dropdown.classList.remove('show'); + }); + this.initRow($rowClone); $row.after($rowClone); diff --git a/app/assets/javascripts/clusters/components/application_row.vue b/app/assets/javascripts/clusters/components/application_row.vue index c2a35341eb2..fae580c091b 100644 --- a/app/assets/javascripts/clusters/components/application_row.vue +++ b/app/assets/javascripts/clusters/components/application_row.vue @@ -179,7 +179,7 @@ role="row" > <div - class="alert alert-danger alert-block append-bottom-0 table-section section-100" + class="alert alert-danger alert-block append-bottom-0" role="gridcell" > <div> diff --git a/app/assets/javascripts/clusters/components/applications.vue b/app/assets/javascripts/clusters/components/applications.vue index 9c12b89240c..bb5fcea648d 100644 --- a/app/assets/javascripts/clusters/components/applications.vue +++ b/app/assets/javascripts/clusters/components/applications.vue @@ -191,11 +191,11 @@ export default { :value="ingressExternalIp" readonly /> - <span class="input-group-btn"> + <span class="input-group-append"> <clipboard-button :text="ingressExternalIp" :title="s__('ClusterIntegration|Copy Ingress IP Address to clipboard')" - class="js-clipboard-btn" + class="input-group-text js-clipboard-btn" /> </span> </div> diff --git a/app/assets/javascripts/commons/bootstrap.js b/app/assets/javascripts/commons/bootstrap.js index db96da4ccba..50e2949ab55 100644 --- a/app/assets/javascripts/commons/bootstrap.js +++ b/app/assets/javascripts/commons/bootstrap.js @@ -1,15 +1,7 @@ import $ from 'jquery'; // bootstrap jQuery plugins -import 'bootstrap-sass/assets/javascripts/bootstrap/affix'; -import 'bootstrap-sass/assets/javascripts/bootstrap/alert'; -import 'bootstrap-sass/assets/javascripts/bootstrap/button'; -import 'bootstrap-sass/assets/javascripts/bootstrap/dropdown'; -import 'bootstrap-sass/assets/javascripts/bootstrap/modal'; -import 'bootstrap-sass/assets/javascripts/bootstrap/tab'; -import 'bootstrap-sass/assets/javascripts/bootstrap/transition'; -import 'bootstrap-sass/assets/javascripts/bootstrap/tooltip'; -import 'bootstrap-sass/assets/javascripts/bootstrap/popover'; +import 'bootstrap'; // custom jQuery functions $.fn.extend({ diff --git a/app/assets/javascripts/compare_autocomplete.js b/app/assets/javascripts/compare_autocomplete.js index 9c88466e576..ffe15f02f2e 100644 --- a/app/assets/javascripts/compare_autocomplete.js +++ b/app/assets/javascripts/compare_autocomplete.js @@ -54,7 +54,7 @@ export default function initCompareAutocomplete(limitTo = null, clickHandler = ( .attr('href', '#') .addClass(ref === selected ? 'is-active' : '') .text(ref) - .attr('data-ref', escape(ref)); + .attr('data-ref', ref); return $('<li />').append(link); } }, @@ -78,7 +78,7 @@ export default function initCompareAutocomplete(limitTo = null, clickHandler = ( $dropdownContainer.on('click', '.dropdown-content a', e => { $dropdown.prop('title', e.target.text.replace(/_+?/g, '-')); if ($dropdown.hasClass('has-tooltip')) { - $dropdown.tooltip('fixTitle'); + $dropdown.tooltip('_fixTitle'); } }); }); diff --git a/app/assets/javascripts/create_merge_request_dropdown.js b/app/assets/javascripts/create_merge_request_dropdown.js index a88b6971f90..09d490106df 100644 --- a/app/assets/javascripts/create_merge_request_dropdown.js +++ b/app/assets/javascripts/create_merge_request_dropdown.js @@ -61,8 +61,8 @@ export default class CreateMergeRequestDropdown { } available() { - this.availableButton.classList.remove('hide'); - this.unavailableButton.classList.add('hide'); + this.availableButton.classList.remove('hidden'); + this.unavailableButton.classList.add('hidden'); } bindEvents() { @@ -232,7 +232,7 @@ export default class CreateMergeRequestDropdown { } hide() { - this.wrapperEl.classList.add('hide'); + this.wrapperEl.classList.add('hidden'); } init() { @@ -406,8 +406,8 @@ export default class CreateMergeRequestDropdown { } unavailable() { - this.availableButton.classList.add('hide'); - this.unavailableButton.classList.remove('hide'); + this.availableButton.classList.add('hidden'); + this.unavailableButton.classList.remove('hidden'); } updateBranchName(suggestedBranchName) { diff --git a/app/assets/javascripts/cycle_analytics/components/limit_warning_component.vue b/app/assets/javascripts/cycle_analytics/components/limit_warning_component.vue index 32ae0cc1476..5be17081b58 100644 --- a/app/assets/javascripts/cycle_analytics/components/limit_warning_component.vue +++ b/app/assets/javascripts/cycle_analytics/components/limit_warning_component.vue @@ -16,7 +16,7 @@ <template> <span v-if="count === 50" - class="events-info pull-right" + class="events-info float-right" > <i class="fa fa-warning" diff --git a/app/assets/javascripts/diff_notes/components/diff_note_avatars.js b/app/assets/javascripts/diff_notes/components/diff_note_avatars.js index 180a6bd67e7..fe9b0795609 100644 --- a/app/assets/javascripts/diff_notes/components/diff_note_avatars.js +++ b/app/assets/javascripts/diff_notes/components/diff_note_avatars.js @@ -79,7 +79,7 @@ const DiffNoteAvatars = Vue.extend({ storeState: { handler() { this.$nextTick(() => { - $('.has-tooltip', this.$el).tooltip('fixTitle'); + $('.has-tooltip', this.$el).tooltip('_fixTitle'); // We need to add/remove a class to an element that is outside the Vue instance this.addNoCommentClass(); @@ -138,7 +138,7 @@ const DiffNoteAvatars = Vue.extend({ this.$nextTick(() => { this.setDiscussionVisible(); - $('.has-tooltip', this.$el).tooltip('fixTitle'); + $('.has-tooltip', this.$el).tooltip('_fixTitle'); $('.has-tooltip', this.$el).tooltip('hide'); }); }, diff --git a/app/assets/javascripts/diff_notes/components/resolve_btn.js b/app/assets/javascripts/diff_notes/components/resolve_btn.js index df4c72ba0ed..8d66417abac 100644 --- a/app/assets/javascripts/diff_notes/components/resolve_btn.js +++ b/app/assets/javascripts/diff_notes/components/resolve_btn.js @@ -61,7 +61,7 @@ const ResolveBtn = Vue.extend({ this.$nextTick(() => { $(this.$refs.button) .tooltip('hide') - .tooltip('fixTitle'); + .tooltip('_fixTitle'); }); }, resolve: function () { diff --git a/app/assets/javascripts/environments/components/environment_actions.vue b/app/assets/javascripts/environments/components/environment_actions.vue index ab9e22037d0..0b3fef9fcca 100644 --- a/app/assets/javascripts/environments/components/environment_actions.vue +++ b/app/assets/javascripts/environments/components/environment_actions.vue @@ -74,7 +74,7 @@ </span> </button> - <ul class="dropdown-menu dropdown-menu-align-right"> + <ul class="dropdown-menu dropdown-menu-right"> <li v-for="(action, i) in actions" :key="i"> diff --git a/app/assets/javascripts/environments/components/environment_item.vue b/app/assets/javascripts/environments/components/environment_item.vue index 79326ca3487..23aaab2c441 100644 --- a/app/assets/javascripts/environments/components/environment_item.vue +++ b/app/assets/javascripts/environments/components/environment_item.vue @@ -486,14 +486,14 @@ {{ model.folderName }} </span> - <span class="badge"> + <span class="badge badge-pill"> {{ model.size }} </span> </span> </div> <div - class="table-section section-10 deployment-column hidden-xs hidden-sm" + class="table-section section-10 deployment-column d-none d-sm-none d-md-block" role="gridcell" > <span v-if="shouldRenderDeploymentID"> @@ -513,7 +513,7 @@ </div> <div - class="table-section section-15 hidden-xs hidden-sm" + class="table-section section-15 d-none d-sm-none d-md-block" role="gridcell" > <a diff --git a/app/assets/javascripts/environments/components/environment_monitoring.vue b/app/assets/javascripts/environments/components/environment_monitoring.vue index deada134b27..8df1b6317e3 100644 --- a/app/assets/javascripts/environments/components/environment_monitoring.vue +++ b/app/assets/javascripts/environments/components/environment_monitoring.vue @@ -28,7 +28,7 @@ <template> <a v-tooltip - class="btn monitoring-url hidden-xs hidden-sm" + class="btn monitoring-url d-none d-sm-none d-md-block" data-container="body" rel="noopener noreferrer nofollow" :href="monitoringUrl" diff --git a/app/assets/javascripts/environments/components/environment_rollback.vue b/app/assets/javascripts/environments/components/environment_rollback.vue index c822fb1574c..7515d711c50 100644 --- a/app/assets/javascripts/environments/components/environment_rollback.vue +++ b/app/assets/javascripts/environments/components/environment_rollback.vue @@ -40,7 +40,7 @@ <template> <button type="button" - class="btn hidden-xs hidden-sm" + class="btn d-none d-sm-none d-md-block" @click="onClick" :disabled="isLoading" > diff --git a/app/assets/javascripts/environments/components/environment_stop.vue b/app/assets/javascripts/environments/components/environment_stop.vue index dda7429a726..7055f208451 100644 --- a/app/assets/javascripts/environments/components/environment_stop.vue +++ b/app/assets/javascripts/environments/components/environment_stop.vue @@ -43,7 +43,7 @@ if (confirm('Are you sure you want to stop this environment?')) { this.isLoading = true; - $(this.$el).tooltip('destroy'); + $(this.$el).tooltip('dispose'); eventHub.$emit('postAction', this.stopUrl); } @@ -55,7 +55,7 @@ <button v-tooltip type="button" - class="btn stop-env-link hidden-xs hidden-sm" + class="btn stop-env-link d-none d-sm-none d-md-block" data-container="body" @click="onClick" :disabled="isLoading" diff --git a/app/assets/javascripts/environments/components/environment_terminal_button.vue b/app/assets/javascripts/environments/components/environment_terminal_button.vue index e8469d088ef..0dbbbb75e07 100644 --- a/app/assets/javascripts/environments/components/environment_terminal_button.vue +++ b/app/assets/javascripts/environments/components/environment_terminal_button.vue @@ -30,7 +30,7 @@ <template> <a v-tooltip - class="btn terminal-button hidden-xs hidden-sm" + class="btn terminal-button d-none d-sm-none d-md-block" data-container="body" :title="title" :aria-label="title" diff --git a/app/assets/javascripts/environments/components/environments_app.vue b/app/assets/javascripts/environments/components/environments_app.vue index c0be72f7401..3da762446c9 100644 --- a/app/assets/javascripts/environments/components/environments_app.vue +++ b/app/assets/javascripts/environments/components/environments_app.vue @@ -68,8 +68,7 @@ this.store.updateEnvironmentProp(folder, 'isLoadingFolderContent', showLoader); this.service.getFolderContent(folder.folder_path) - .then(resp => resp.json()) - .then(response => this.store.setfolderContent(folder, response.environments)) + .then(response => this.store.setfolderContent(folder, response.data.environments)) .then(() => this.store.updateEnvironmentProp(folder, 'isLoadingFolderContent', false)) .catch(() => { Flash(s__('Environments|An error occurred while fetching the environments.')); diff --git a/app/assets/javascripts/environments/mixins/environments_mixin.js b/app/assets/javascripts/environments/mixins/environments_mixin.js index 34d18d55120..a7a79dbca70 100644 --- a/app/assets/javascripts/environments/mixins/environments_mixin.js +++ b/app/assets/javascripts/environments/mixins/environments_mixin.js @@ -6,7 +6,6 @@ import Visibility from 'visibilityjs'; import Poll from '../../lib/utils/poll'; import { getParameterByName, - parseQueryStringIntoObject, } from '../../lib/utils/common_utils'; import { s__ } from '../../locale'; import Flash from '../../flash'; @@ -46,17 +45,14 @@ export default { methods: { saveData(resp) { - const headers = resp.headers; - return resp.json().then((response) => { - this.isLoading = false; - - if (_.isEqual(parseQueryStringIntoObject(resp.url.split('?')[1]), this.requestData)) { - this.store.storeAvailableCount(response.available_count); - this.store.storeStoppedCount(response.stopped_count); - this.store.storeEnvironments(response.environments); - this.store.setPagination(headers); - } - }); + this.isLoading = false; + + if (_.isEqual(resp.config.params, this.requestData)) { + this.store.storeAvailableCount(resp.data.available_count); + this.store.storeStoppedCount(resp.data.stopped_count); + this.store.storeEnvironments(resp.data.environments); + this.store.setPagination(resp.headers); + } }, /** @@ -70,7 +66,7 @@ export default { updateContent(parameters) { this.updateInternalState(parameters); // fetch new data - return this.service.get(this.requestData) + return this.service.fetchEnvironments(this.requestData) .then(response => this.successCallback(response)) .then(() => { // restart polling @@ -105,7 +101,7 @@ export default { fetchEnvironments() { this.isLoading = true; - return this.service.get(this.requestData) + return this.service.fetchEnvironments(this.requestData) .then(this.successCallback) .catch(this.errorCallback); }, @@ -141,7 +137,7 @@ export default { this.poll = new Poll({ resource: this.service, - method: 'get', + method: 'fetchEnvironments', data: this.requestData, successCallback: this.successCallback, errorCallback: this.errorCallback, diff --git a/app/assets/javascripts/environments/services/environments_service.js b/app/assets/javascripts/environments/services/environments_service.js index 03ab74b3338..3b121551aca 100644 --- a/app/assets/javascripts/environments/services/environments_service.js +++ b/app/assets/javascripts/environments/services/environments_service.js @@ -1,25 +1,22 @@ -/* eslint-disable class-methods-use-this */ -import Vue from 'vue'; -import VueResource from 'vue-resource'; - -Vue.use(VueResource); +import axios from '~/lib/utils/axios_utils'; export default class EnvironmentsService { constructor(endpoint) { - this.environments = Vue.resource(endpoint); + this.environmentsEndpoint = endpoint; this.folderResults = 3; } - get(options = {}) { + fetchEnvironments(options = {}) { const { scope, page } = options; - return this.environments.get({ scope, page }); + return axios.get(this.environmentsEndpoint, { params: { scope, page } }); } + // eslint-disable-next-line class-methods-use-this postAction(endpoint) { - return Vue.http.post(endpoint, {}, { emulateJSON: true }); + return axios.post(endpoint, {}, { emulateJSON: true }); } getFolderContent(folderUrl) { - return Vue.http.get(`${folderUrl}.json?per_page=${this.folderResults}`); + return axios.get(`${folderUrl}.json?per_page=${this.folderResults}`); } } diff --git a/app/assets/javascripts/feature_highlight/feature_highlight.js b/app/assets/javascripts/feature_highlight/feature_highlight.js index 2d5bae9a9c4..2f27c9351bc 100644 --- a/app/assets/javascripts/feature_highlight/feature_highlight.js +++ b/app/assets/javascripts/feature_highlight/feature_highlight.js @@ -24,7 +24,7 @@ export function setupFeatureHighlightPopover(id, debounceTimeout = 300) { template: ` <div class="popover feature-highlight-popover" role="tooltip"> <div class="arrow"></div> - <div class="popover-content"></div> + <div class="popover-body"></div> </div> `, }) diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js index fa48d7d1915..746a06b7c4f 100644 --- a/app/assets/javascripts/gl_dropdown.js +++ b/app/assets/javascripts/gl_dropdown.js @@ -374,7 +374,7 @@ GitLabDropdown = (function() { $relatedTarget = $(e.relatedTarget); $dropdownMenu = $relatedTarget.closest('.dropdown-menu'); if ($dropdownMenu.length === 0) { - return _this.dropdown.removeClass('open'); + return _this.dropdown.removeClass('show'); } } }; @@ -801,7 +801,7 @@ GitLabDropdown = (function() { if (this.options.filterable) { const initialScrollTop = $(window).scrollTop(); - if (this.dropdown.is('.open')) { + if (this.dropdown.is('.show') && !this.filterInput.is(':focus')) { this.filterInput.focus(); } diff --git a/app/assets/javascripts/gl_field_error.js b/app/assets/javascripts/gl_field_error.js index 972b2252acb..87c6e37b9fb 100644 --- a/app/assets/javascripts/gl_field_error.js +++ b/app/assets/javascripts/gl_field_error.js @@ -62,7 +62,7 @@ export default class GlFieldError { this.inputDomElement = this.inputElement.get(0); this.form = formErrors; this.errorMessage = this.inputElement.attr('title') || 'This field is required.'; - this.fieldErrorElement = $(`<p class='${errorMessageClass} hide'>${this.errorMessage}</p>`); + this.fieldErrorElement = $(`<p class='${errorMessageClass} hidden'>${this.errorMessage}</p>`); this.state = { valid: false, @@ -146,8 +146,8 @@ export default class GlFieldError { renderInvalid() { this.inputElement.addClass(inputErrorClass); - this.scopedSiblings.hide(); - return this.fieldErrorElement.show(); + this.scopedSiblings.addClass('hidden'); + return this.fieldErrorElement.removeClass('hidden'); } renderClear() { @@ -157,7 +157,7 @@ export default class GlFieldError { this.accessCurrentValue(trimmedInput); } this.inputElement.removeClass(inputErrorClass); - this.scopedSiblings.hide(); - this.fieldErrorElement.hide(); + this.scopedSiblings.addClass('hidden'); + this.fieldErrorElement.addClass('hidden'); } } diff --git a/app/assets/javascripts/groups/components/group_item.vue b/app/assets/javascripts/groups/components/group_item.vue index 764b130fdb8..7f64a9bd741 100644 --- a/app/assets/javascripts/groups/components/group_item.vue +++ b/app/assets/javascripts/groups/components/group_item.vue @@ -99,7 +99,7 @@ export default { /> </div> <div - class="avatar-container prepend-top-8 prepend-left-5 s24 hidden-xs" + class="avatar-container prepend-top-8 prepend-left-5 s24 d-none d-sm-block" :class="{ 'content-loading': group.isChildrenLoading }" > <a diff --git a/app/assets/javascripts/ide/components/commit_sidebar/form.vue b/app/assets/javascripts/ide/components/commit_sidebar/form.vue index 4a645c827ad..81961fe3c57 100644 --- a/app/assets/javascripts/ide/components/commit_sidebar/form.vue +++ b/app/assets/javascripts/ide/components/commit_sidebar/form.vue @@ -5,7 +5,7 @@ import LoadingButton from '~/vue_shared/components/loading_button.vue'; import CommitMessageField from './message_field.vue'; import Actions from './actions.vue'; import SuccessMessage from './success_message.vue'; -import { activityBarViews, MAX_WINDOW_HEIGHT_COMPACT, COMMIT_ITEM_PADDING } from '../../constants'; +import { activityBarViews, MAX_WINDOW_HEIGHT_COMPACT } from '../../constants'; export default { components: { @@ -70,7 +70,7 @@ export default { ? this.$refs.formEl && this.$refs.formEl.offsetHeight : this.$refs.compactEl && this.$refs.compactEl.offsetHeight; - this.componentHeight = elHeight + COMMIT_ITEM_PADDING; + this.componentHeight = elHeight; }, enterTransition() { this.$nextTick(() => { @@ -78,7 +78,7 @@ export default { ? this.$refs.compactEl && this.$refs.compactEl.offsetHeight : this.$refs.formEl && this.$refs.formEl.offsetHeight; - this.componentHeight = elHeight + COMMIT_ITEM_PADDING; + this.componentHeight = elHeight; }); }, afterEndTransition() { diff --git a/app/assets/javascripts/ide/components/file_finder/index.vue b/app/assets/javascripts/ide/components/file_finder/index.vue index ea2b13a8b21..cabb3f59b17 100644 --- a/app/assets/javascripts/ide/components/file_finder/index.vue +++ b/app/assets/javascripts/ide/components/file_finder/index.vue @@ -39,12 +39,10 @@ export default { return this.allBlobs.slice(0, MAX_FILE_FINDER_RESULTS); } - return fuzzaldrinPlus - .filter(this.allBlobs, searchText, { - key: 'path', - maxResults: MAX_FILE_FINDER_RESULTS, - }) - .sort((a, b) => b.lastOpenedAt - a.lastOpenedAt); + return fuzzaldrinPlus.filter(this.allBlobs, searchText, { + key: 'path', + maxResults: MAX_FILE_FINDER_RESULTS, + }); }, filteredBlobsLength() { return this.filteredBlobs.length; diff --git a/app/assets/javascripts/ide/components/ide.vue b/app/assets/javascripts/ide/components/ide.vue index 6c373a92776..2c184ea726c 100644 --- a/app/assets/javascripts/ide/components/ide.vue +++ b/app/assets/javascripts/ide/components/ide.vue @@ -52,7 +52,10 @@ export default { methods: { ...mapActions(['toggleFileFinder']), mousetrapStopCallback(e, el, combo) { - if (combo === 't' && el.classList.contains('dropdown-input-field')) { + if ( + (combo === 't' && el.classList.contains('dropdown-input-field')) || + el.classList.contains('inputarea') + ) { return true; } else if (combo === 'command+p' || combo === 'ctrl+p') { return false; @@ -99,12 +102,12 @@ export default { class="ide-empty-state" > <div class="row js-empty-state"> - <div class="col-xs-12"> + <div class="col-12"> <div class="svg-content svg-250"> <img :src="emptyStateSvgPath" /> </div> </div> - <div class="col-xs-12"> + <div class="col-12"> <div class="text-content text-center"> <h4> Welcome to the GitLab IDE @@ -120,8 +123,6 @@ export default { </template> </div> </div> - <ide-status-bar - :file="activeFile" - /> + <ide-status-bar :file="activeFile"/> </article> </template> diff --git a/app/assets/javascripts/ide/components/ide_file_buttons.vue b/app/assets/javascripts/ide/components/ide_file_buttons.vue index a6c6f46a144..30b00abf6ed 100644 --- a/app/assets/javascripts/ide/components/ide_file_buttons.vue +++ b/app/assets/javascripts/ide/components/ide_file_buttons.vue @@ -32,14 +32,14 @@ export default { <template> <div v-if="showButtons" - class="pull-right ide-btn-group" + class="float-right ide-btn-group" > <a v-tooltip v-if="!file.binary" :href="file.blamePath" :title="__('Blame')" - class="btn btn-xs btn-transparent blame" + class="btn btn-sm btn-transparent blame" > <icon name="blame" @@ -50,7 +50,7 @@ export default { v-tooltip :href="file.commitsPath" :title="__('History')" - class="btn btn-xs btn-transparent history" + class="btn btn-sm btn-transparent history" > <icon name="history" @@ -61,7 +61,7 @@ export default { v-tooltip :href="file.permalink" :title="__('Permalink')" - class="btn btn-xs btn-transparent permalink" + class="btn btn-sm btn-transparent permalink" > <icon name="link" @@ -72,7 +72,7 @@ export default { v-tooltip :href="file.rawPath" target="_blank" - class="btn btn-xs btn-transparent prepend-left-10 raw" + class="btn btn-sm btn-transparent prepend-left-10 raw" rel="noopener noreferrer" :title="rawDownloadButtonLabel"> <icon diff --git a/app/assets/javascripts/ide/components/ide_status_bar.vue b/app/assets/javascripts/ide/components/ide_status_bar.vue index 70c6d53c3ab..6f60cfbf184 100644 --- a/app/assets/javascripts/ide/components/ide_status_bar.vue +++ b/app/assets/javascripts/ide/components/ide_status_bar.vue @@ -1,14 +1,16 @@ <script> -import { mapGetters } from 'vuex'; +import { mapActions, mapState, mapGetters } from 'vuex'; import icon from '~/vue_shared/components/icon.vue'; import tooltip from '~/vue_shared/directives/tooltip'; import timeAgoMixin from '~/vue_shared/mixins/timeago'; +import CiIcon from '../../vue_shared/components/ci_icon.vue'; import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue'; export default { components: { icon, userAvatarImage, + CiIcon, }, directives: { tooltip, @@ -27,8 +29,16 @@ export default { }; }, computed: { + ...mapState(['currentBranchId', 'currentProjectId']), ...mapGetters(['currentProject', 'lastCommit']), }, + watch: { + lastCommit() { + if (!this.isPollingInitialized) { + this.initPipelinePolling(); + } + }, + }, mounted() { this.startTimer(); }, @@ -36,13 +46,21 @@ export default { if (this.intervalId) { clearInterval(this.intervalId); } + if (this.isPollingInitialized) { + this.stopPipelinePolling(); + } }, methods: { + ...mapActions(['pipelinePoll', 'stopPipelinePolling']), startTimer() { this.intervalId = setInterval(() => { this.commitAgeUpdate(); }, 1000); }, + initPipelinePolling() { + this.pipelinePoll(); + this.isPollingInitialized = true; + }, commitAgeUpdate() { if (this.lastCommit) { this.lastCommitFormatedAge = this.timeFormated(this.lastCommit.committed_date); @@ -61,6 +79,23 @@ export default { class="ide-status-branch" v-if="lastCommit && lastCommitFormatedAge" > + <span + class="ide-status-pipeline" + v-if="lastCommit.pipeline && lastCommit.pipeline.details" + > + <ci-icon + :status="lastCommit.pipeline.details.status" + v-tooltip + :title="lastCommit.pipeline.details.status.text" + /> + Pipeline + <a + class="monospace" + :href="lastCommit.pipeline.details.status.details_path">#{{ lastCommit.pipeline.id }}</a> + {{ lastCommit.pipeline.details.status.text }} + for + </span> + <icon name="commit" /> diff --git a/app/assets/javascripts/ide/components/new_dropdown/index.vue b/app/assets/javascripts/ide/components/new_dropdown/index.vue index a0ce1c9dac7..f0b29702497 100644 --- a/app/assets/javascripts/ide/components/new_dropdown/index.vue +++ b/app/assets/javascripts/ide/components/new_dropdown/index.vue @@ -57,7 +57,7 @@ export default { <div class="dropdown" :class="{ - open: dropdownOpen, + show: dropdownOpen, }" > <button @@ -69,12 +69,12 @@ export default { <icon name="plus" :size="12" - css-classes="pull-left" + css-classes="float-left" /> <icon name="arrow-down" :size="12" - css-classes="pull-left" + css-classes="float-left" /> </button> <ul diff --git a/app/assets/javascripts/ide/components/new_dropdown/modal.vue b/app/assets/javascripts/ide/components/new_dropdown/modal.vue index a95a0225950..d83a90f71e1 100644 --- a/app/assets/javascripts/ide/components/new_dropdown/modal.vue +++ b/app/assets/javascripts/ide/components/new_dropdown/modal.vue @@ -70,12 +70,12 @@ export default { @submit="createEntryInStore" > <form - class="form-horizontal" slot="body" @submit.prevent="createEntryInStore" + class="form-group row append-bottom-0" > <fieldset class="form-group append-bottom-0"> - <label class="label-light col-sm-3 ide-new-modal-label"> + <label class="label-light col-form-label col-sm-3 ide-new-modal-label"> {{ __('Name') }} </label> <div class="col-sm-9"> diff --git a/app/assets/javascripts/ide/components/repo_editor.vue b/app/assets/javascripts/ide/components/repo_editor.vue index f8678b602ac..a281ecb95c8 100644 --- a/app/assets/javascripts/ide/components/repo_editor.vue +++ b/app/assets/javascripts/ide/components/repo_editor.vue @@ -43,9 +43,13 @@ export default { }, }, watch: { - file(oldVal, newVal) { + file(newVal, oldVal) { + if (oldVal.pending) { + this.removePendingTab(oldVal); + } + // Compare key to allow for files opened in review mode to be cached differently - if (newVal.key !== this.file.key) { + if (oldVal.key !== this.file.key) { this.initMonaco(); if (this.currentActivityView !== activityBarViews.edit) { @@ -99,6 +103,7 @@ export default { 'setFileViewMode', 'setFileEOL', 'updateViewer', + 'removePendingTab', ]), initMonaco() { if (this.shouldHideEditor) return; @@ -192,7 +197,7 @@ export default { > <div class="ide-mode-tabs clearfix" > <ul - class="nav-links pull-left" + class="nav-links float-left" v-if="!shouldHideEditor && isEditModeActive" > <li :class="editTabCSS"> diff --git a/app/assets/javascripts/ide/components/repo_file.vue b/app/assets/javascripts/ide/components/repo_file.vue index 14946f8c9fa..442697e1c80 100644 --- a/app/assets/javascripts/ide/components/repo_file.vue +++ b/app/assets/javascripts/ide/components/repo_file.vue @@ -122,11 +122,11 @@ export default { <div class="file" :class="fileClass" + @click="clickFile" + role="button" > <div class="file-name" - @click="clickFile" - role="button" > <span class="ide-file-name str-truncated" @@ -144,7 +144,7 @@ export default { :file="file" /> </span> - <span class="pull-right ide-file-icon-holder"> + <span class="float-right ide-file-icon-holder"> <mr-file-icon v-if="file.mrChange" /> @@ -177,7 +177,7 @@ export default { :project-id="file.projectId" :branch="file.branchId" :path="file.path" - class="pull-right prepend-left-8" + class="float-right prepend-left-8" /> </div> </div> diff --git a/app/assets/javascripts/ide/components/repo_loading_file.vue b/app/assets/javascripts/ide/components/repo_loading_file.vue index 79af8c0b0c7..3e47da88050 100644 --- a/app/assets/javascripts/ide/components/repo_loading_file.vue +++ b/app/assets/javascripts/ide/components/repo_loading_file.vue @@ -25,13 +25,13 @@ /> </td> <template v-if="!leftPanelCollapsed"> - <td class="hidden-sm hidden-xs"> + <td class="d-none d-sm-none d-md-block"> <skeleton-loading-container :small="true" /> </td> - <td class="hidden-xs"> + <td class="d-none d-sm-block"> <skeleton-loading-container class="animation-container-right" :small="true" diff --git a/app/assets/javascripts/ide/constants.js b/app/assets/javascripts/ide/constants.js index 48d4cc43198..83fe22f40a4 100644 --- a/app/assets/javascripts/ide/constants.js +++ b/app/assets/javascripts/ide/constants.js @@ -5,8 +5,6 @@ export const FILE_FINDER_EMPTY_ROW_HEIGHT = 33; export const MAX_WINDOW_HEIGHT_COMPACT = 750; -export const COMMIT_ITEM_PADDING = 32; - // Commit message textarea export const MAX_TITLE_LENGTH = 50; export const MAX_BODY_LENGTH = 72; diff --git a/app/assets/javascripts/ide/ide_router.js b/app/assets/javascripts/ide/ide_router.js index adca85dc65b..a21cec4e8d8 100644 --- a/app/assets/javascripts/ide/ide_router.js +++ b/app/assets/javascripts/ide/ide_router.js @@ -41,7 +41,7 @@ const router = new VueRouter({ component: EmptyRouterComponent, children: [ { - path: ':targetmode(edit|tree|blob)/:branch/*', + path: ':targetmode(edit|tree|blob)/*', component: EmptyRouterComponent, }, { @@ -63,23 +63,27 @@ router.beforeEach((to, from, next) => { .then(() => { const fullProjectId = `${to.params.namespace}/${to.params.project}`; - if (to.params.branch) { - store.dispatch('setCurrentBranchId', to.params.branch); + const baseSplit = to.params[0].split('/-/'); + const branchId = baseSplit[0].slice(-1) === '/' ? baseSplit[0].slice(0, -1) : baseSplit[0]; + + if (branchId) { + const basePath = baseSplit.length > 1 ? baseSplit[1] : ''; + + store.dispatch('setCurrentBranchId', branchId); store.dispatch('getBranchData', { projectId: fullProjectId, - branchId: to.params.branch, + branchId, }); store .dispatch('getFiles', { projectId: fullProjectId, - branchId: to.params.branch, + branchId, }) .then(() => { - if (to.params[0]) { - const path = - to.params[0].slice(-1) === '/' ? to.params[0].slice(0, -1) : to.params[0]; + if (basePath) { + const path = basePath.slice(-1) === '/' ? basePath.slice(0, -1) : basePath; const treeEntryKey = Object.keys(store.state.entries).find( key => key === path && !store.state.entries[key].pending, ); diff --git a/app/assets/javascripts/ide/services/index.js b/app/assets/javascripts/ide/services/index.js index a12e637616a..e8b51f2b516 100644 --- a/app/assets/javascripts/ide/services/index.js +++ b/app/assets/javascripts/ide/services/index.js @@ -75,4 +75,8 @@ export default { }, }); }, + lastCommitPipelines({ getters }) { + const commitSha = getters.lastCommit.id; + return Api.commitPipelines(getters.currentProject.path_with_namespace, commitSha); + }, }; diff --git a/app/assets/javascripts/ide/stores/actions/file.js b/app/assets/javascripts/ide/stores/actions/file.js index b6baa693104..13aea91d8ba 100644 --- a/app/assets/javascripts/ide/stores/actions/file.js +++ b/app/assets/javascripts/ide/stores/actions/file.js @@ -63,7 +63,9 @@ export const getFileData = ({ state, commit, dispatch }, { path, makeFileActive const file = state.entries[path]; commit(types.TOGGLE_LOADING, { entry: file }); return service - .getFileData(`${gon.relative_url_root ? gon.relative_url_root : ''}${file.url}`) + .getFileData( + `${gon.relative_url_root ? gon.relative_url_root : ''}${file.url.replace('/-/', '/')}`, + ) .then(res => { const pageTitle = decodeURI(normalizeHeaders(res.headers)['PAGE-TITLE']); setPageTitle(pageTitle); diff --git a/app/assets/javascripts/ide/stores/actions/project.js b/app/assets/javascripts/ide/stores/actions/project.js index eff9bc03651..cece9154c82 100644 --- a/app/assets/javascripts/ide/stores/actions/project.js +++ b/app/assets/javascripts/ide/stores/actions/project.js @@ -1,6 +1,11 @@ +import Visibility from 'visibilityjs'; import flash from '~/flash'; +import { __ } from '~/locale'; import service from '../../services'; import * as types from '../mutation_types'; +import Poll from '../../../lib/utils/poll'; + +let eTagPoll; export const getProjectData = ( { commit, state, dispatch }, @@ -21,7 +26,7 @@ export const getProjectData = ( }) .catch(() => { flash( - 'Error loading project data. Please try again.', + __('Error loading project data. Please try again.'), 'alert', document, null, @@ -59,7 +64,7 @@ export const getBranchData = ( }) .catch(() => { flash( - 'Error loading branch data. Please try again.', + __('Error loading branch data. Please try again.'), 'alert', document, null, @@ -73,25 +78,74 @@ export const getBranchData = ( } }); -export const refreshLastCommitData = ( - { commit, state, dispatch }, - { projectId, branchId } = {}, -) => service - .getBranchData(projectId, branchId) - .then(({ data }) => { - commit(types.SET_BRANCH_COMMIT, { - projectId, - branchId, - commit: data.commit, +export const refreshLastCommitData = ({ commit, state, dispatch }, { projectId, branchId } = {}) => + service + .getBranchData(projectId, branchId) + .then(({ data }) => { + commit(types.SET_BRANCH_COMMIT, { + projectId, + branchId, + commit: data.commit, + }); + }) + .catch(() => { + flash(__('Error loading last commit.'), 'alert', document, null, false, true); }); - }) - .catch(() => { - flash( - 'Error loading last commit.', - 'alert', - document, - null, - false, - true, + +export const pollSuccessCallBack = ({ commit, state, dispatch }, { data }) => { + if (data.pipelines && data.pipelines.length) { + const lastCommitHash = + state.projects[state.currentProjectId].branches[state.currentBranchId].commit.id; + const lastCommitPipeline = data.pipelines.find( + pipeline => pipeline.commit.id === lastCommitHash, ); + commit(types.SET_LAST_COMMIT_PIPELINE, { + projectId: state.currentProjectId, + branchId: state.currentBranchId, + pipeline: lastCommitPipeline || {}, + }); + } + + return data; +}; + +export const pipelinePoll = ({ getters, dispatch }) => { + eTagPoll = new Poll({ + resource: service, + method: 'lastCommitPipelines', + data: { + getters, + }, + successCallback: ({ data }) => dispatch('pollSuccessCallBack', { data }), + errorCallback: () => { + flash( + __('Something went wrong while fetching the latest pipeline status.'), + 'alert', + document, + null, + false, + true, + ); + }, }); + + if (!Visibility.hidden()) { + eTagPoll.makeRequest(); + } + + Visibility.change(() => { + if (!Visibility.hidden()) { + eTagPoll.restart(); + } else { + eTagPoll.stop(); + } + }); +}; + +export const stopPipelinePolling = () => { + eTagPoll.stop(); +}; + +export const restartPipelinePolling = () => { + eTagPoll.restart(); +}; diff --git a/app/assets/javascripts/ide/stores/index.js b/app/assets/javascripts/ide/stores/index.js index 7c82ce7976b..699710055e3 100644 --- a/app/assets/javascripts/ide/stores/index.js +++ b/app/assets/javascripts/ide/stores/index.js @@ -5,6 +5,7 @@ import * as actions from './actions'; import * as getters from './getters'; import mutations from './mutations'; import commitModule from './modules/commit'; +import pipelines from './modules/pipelines'; Vue.use(Vuex); @@ -15,5 +16,6 @@ export default new Vuex.Store({ getters, modules: { commit: commitModule, + pipelines, }, }); diff --git a/app/assets/javascripts/ide/stores/modules/commit/actions.js b/app/assets/javascripts/ide/stores/modules/commit/actions.js index b85246b2502..cd25c3060f2 100644 --- a/app/assets/javascripts/ide/stores/modules/commit/actions.js +++ b/app/assets/javascripts/ide/stores/modules/commit/actions.js @@ -204,17 +204,23 @@ export const commitChanges = ({ commit, state, getters, dispatch, rootState, roo dispatch('updateViewer', 'editor', { root: true }); router.push( - `/project/${rootState.currentProjectId}/blob/${getters.branchName}/${ + `/project/${rootState.currentProjectId}/blob/${getters.branchName}/-/${ rootGetters.activeFile.path }`, ); } }) .then(() => dispatch('updateCommitAction', consts.COMMIT_TO_CURRENT_BRANCH)) - .then(() => dispatch('refreshLastCommitData', { - projectId: rootState.currentProjectId, - branchId: rootState.currentBranchId, - }, { root: true })); + .then(() => + dispatch( + 'refreshLastCommitData', + { + projectId: rootState.currentProjectId, + branchId: rootState.currentBranchId, + }, + { root: true }, + ), + ); }) .catch(err => { let errMsg = __('Error committing changes. Please try again.'); diff --git a/app/assets/javascripts/ide/stores/modules/pipelines/actions.js b/app/assets/javascripts/ide/stores/modules/pipelines/actions.js new file mode 100644 index 00000000000..07f7b201f2e --- /dev/null +++ b/app/assets/javascripts/ide/stores/modules/pipelines/actions.js @@ -0,0 +1,49 @@ +import { __ } from '../../../../locale'; +import Api from '../../../../api'; +import flash from '../../../../flash'; +import * as types from './mutation_types'; + +export const requestLatestPipeline = ({ commit }) => commit(types.REQUEST_LATEST_PIPELINE); +export const receiveLatestPipelineError = ({ commit }) => { + flash(__('There was an error loading latest pipeline')); + commit(types.RECEIVE_LASTEST_PIPELINE_ERROR); +}; +export const receiveLatestPipelineSuccess = ({ commit }, pipeline) => + commit(types.RECEIVE_LASTEST_PIPELINE_SUCCESS, pipeline); + +export const fetchLatestPipeline = ({ dispatch, rootState }, sha) => { + dispatch('requestLatestPipeline'); + + return Api.pipelines(rootState.currentProjectId, { sha, per_page: '1' }) + .then(({ data }) => { + dispatch('receiveLatestPipelineSuccess', data.pop()); + }) + .catch(() => dispatch('receiveLatestPipelineError')); +}; + +export const requestJobs = ({ commit }) => commit(types.REQUEST_JOBS); +export const receiveJobsError = ({ commit }) => { + flash(__('There was an error loading jobs')); + commit(types.RECEIVE_JOBS_ERROR); +}; +export const receiveJobsSuccess = ({ commit }, data) => commit(types.RECEIVE_JOBS_SUCCESS, data); + +export const fetchJobs = ({ dispatch, state, rootState }, page = '1') => { + dispatch('requestJobs'); + + Api.pipelineJobs(rootState.currentProjectId, state.latestPipeline.id, { + page, + }) + .then(({ data, headers }) => { + const nextPage = headers && headers['x-next-page']; + + dispatch('receiveJobsSuccess', data); + + if (nextPage) { + dispatch('fetchJobs', nextPage); + } + }) + .catch(() => dispatch('receiveJobsError')); +}; + +export default () => {}; diff --git a/app/assets/javascripts/ide/stores/modules/pipelines/getters.js b/app/assets/javascripts/ide/stores/modules/pipelines/getters.js new file mode 100644 index 00000000000..d6c91f5b64d --- /dev/null +++ b/app/assets/javascripts/ide/stores/modules/pipelines/getters.js @@ -0,0 +1,7 @@ +export const hasLatestPipeline = state => !state.isLoadingPipeline && !!state.latestPipeline; + +export const failedJobs = state => + state.stages.reduce( + (acc, stage) => acc.concat(stage.jobs.filter(job => job.status === 'failed')), + [], + ); diff --git a/app/assets/javascripts/ide/stores/modules/pipelines/index.js b/app/assets/javascripts/ide/stores/modules/pipelines/index.js new file mode 100644 index 00000000000..b44c3141b81 --- /dev/null +++ b/app/assets/javascripts/ide/stores/modules/pipelines/index.js @@ -0,0 +1,12 @@ +import state from './state'; +import * as actions from './actions'; +import mutations from './mutations'; +import * as getters from './getters'; + +export default { + namespaced: true, + state: state(), + actions, + mutations, + getters, +}; diff --git a/app/assets/javascripts/ide/stores/modules/pipelines/mutation_types.js b/app/assets/javascripts/ide/stores/modules/pipelines/mutation_types.js new file mode 100644 index 00000000000..6b5701670a6 --- /dev/null +++ b/app/assets/javascripts/ide/stores/modules/pipelines/mutation_types.js @@ -0,0 +1,7 @@ +export const REQUEST_LATEST_PIPELINE = 'REQUEST_LATEST_PIPELINE'; +export const RECEIVE_LASTEST_PIPELINE_ERROR = 'RECEIVE_LASTEST_PIPELINE_ERROR'; +export const RECEIVE_LASTEST_PIPELINE_SUCCESS = 'RECEIVE_LASTEST_PIPELINE_SUCCESS'; + +export const REQUEST_JOBS = 'REQUEST_JOBS'; +export const RECEIVE_JOBS_ERROR = 'RECEIVE_JOBS_ERROR'; +export const RECEIVE_JOBS_SUCCESS = 'RECEIVE_JOBS_SUCCESS'; diff --git a/app/assets/javascripts/ide/stores/modules/pipelines/mutations.js b/app/assets/javascripts/ide/stores/modules/pipelines/mutations.js new file mode 100644 index 00000000000..2b16e57b386 --- /dev/null +++ b/app/assets/javascripts/ide/stores/modules/pipelines/mutations.js @@ -0,0 +1,53 @@ +/* eslint-disable no-param-reassign */ +import * as types from './mutation_types'; + +export default { + [types.REQUEST_LATEST_PIPELINE](state) { + state.isLoadingPipeline = true; + }, + [types.RECEIVE_LASTEST_PIPELINE_ERROR](state) { + state.isLoadingPipeline = false; + }, + [types.RECEIVE_LASTEST_PIPELINE_SUCCESS](state, pipeline) { + state.isLoadingPipeline = false; + + if (pipeline) { + state.latestPipeline = { + id: pipeline.id, + status: pipeline.status, + }; + } + }, + [types.REQUEST_JOBS](state) { + state.isLoadingJobs = true; + }, + [types.RECEIVE_JOBS_ERROR](state) { + state.isLoadingJobs = false; + }, + [types.RECEIVE_JOBS_SUCCESS](state, jobs) { + state.isLoadingJobs = false; + + state.stages = jobs.reduce((acc, job) => { + let stage = acc.find(s => s.title === job.stage); + + if (!stage) { + stage = { + title: job.stage, + jobs: [], + }; + + acc.push(stage); + } + + stage.jobs = stage.jobs.concat({ + id: job.id, + name: job.name, + status: job.status, + stage: job.stage, + duration: job.duration, + }); + + return acc; + }, state.stages); + }, +}; diff --git a/app/assets/javascripts/ide/stores/modules/pipelines/state.js b/app/assets/javascripts/ide/stores/modules/pipelines/state.js new file mode 100644 index 00000000000..6f22542aaea --- /dev/null +++ b/app/assets/javascripts/ide/stores/modules/pipelines/state.js @@ -0,0 +1,6 @@ +export default () => ({ + isLoadingPipeline: false, + isLoadingJobs: false, + latestPipeline: null, + stages: [], +}); diff --git a/app/assets/javascripts/ide/stores/mutation_types.js b/app/assets/javascripts/ide/stores/mutation_types.js index a3fb3232f1d..0a3f8d031c4 100644 --- a/app/assets/javascripts/ide/stores/mutation_types.js +++ b/app/assets/javascripts/ide/stores/mutation_types.js @@ -23,6 +23,7 @@ export const SET_BRANCH = 'SET_BRANCH'; export const SET_BRANCH_COMMIT = 'SET_BRANCH_COMMIT'; export const SET_BRANCH_WORKING_REFERENCE = 'SET_BRANCH_WORKING_REFERENCE'; export const TOGGLE_BRANCH_OPEN = 'TOGGLE_BRANCH_OPEN'; +export const SET_LAST_COMMIT_PIPELINE = 'SET_LAST_COMMIT_PIPELINE'; // Tree mutation types export const SET_DIRECTORY_DATA = 'SET_DIRECTORY_DATA'; diff --git a/app/assets/javascripts/ide/stores/mutations/branch.js b/app/assets/javascripts/ide/stores/mutations/branch.js index e09f88878f4..f17ec4da308 100644 --- a/app/assets/javascripts/ide/stores/mutations/branch.js +++ b/app/assets/javascripts/ide/stores/mutations/branch.js @@ -14,6 +14,10 @@ export default { treeId: `${projectPath}/${branchName}`, active: true, workingReference: '', + commit: { + ...branch.commit, + pipeline: {}, + }, }, }, }); @@ -28,4 +32,9 @@ export default { commit, }); }, + [types.SET_LAST_COMMIT_PIPELINE](state, { projectId, branchId, pipeline }) { + Object.assign(state.projects[projectId].branches[branchId].commit, { + pipeline, + }); + }, }; diff --git a/app/assets/javascripts/ide/stores/workers/files_decorator_worker.js b/app/assets/javascripts/ide/stores/workers/files_decorator_worker.js index d249b05f47c..0a1c253c637 100644 --- a/app/assets/javascripts/ide/stores/workers/files_decorator_worker.js +++ b/app/assets/javascripts/ide/stores/workers/files_decorator_worker.js @@ -26,7 +26,7 @@ self.addEventListener('message', e => { id: folderPath, name: folderName, path: folderPath, - url: `/${projectId}/tree/${branchId}/${folderPath}/`, + url: `/${projectId}/tree/${branchId}/-/${folderPath}/`, type: 'tree', parentTreeUrl: parentFolder ? parentFolder.url : `/${projectId}/tree/${branchId}/`, tempFile, @@ -64,7 +64,7 @@ self.addEventListener('message', e => { id: path, name: blobName, path, - url: `/${projectId}/blob/${branchId}/${path}`, + url: `/${projectId}/blob/${branchId}/-/${path}`, type: 'blob', parentTreeUrl: fileFolder ? fileFolder.url : `/${projectId}/blob/${branchId}`, tempFile, diff --git a/app/assets/javascripts/issue_show/components/edit_actions.vue b/app/assets/javascripts/issue_show/components/edit_actions.vue index a539506bce2..7ef5e679881 100644 --- a/app/assets/javascripts/issue_show/components/edit_actions.vue +++ b/app/assets/javascripts/issue_show/components/edit_actions.vue @@ -51,7 +51,7 @@ <template> <div class="prepend-top-default append-bottom-default clearfix"> <button - class="btn btn-save pull-left" + class="btn btn-save float-left" :class="{ disabled: formState.updateLoading || !isSubmitEnabled }" type="submit" :disabled="formState.updateLoading || !isSubmitEnabled" @@ -64,14 +64,14 @@ </i> </button> <button - class="btn btn-default pull-right" + class="btn btn-default float-right" type="button" @click="closeForm"> Cancel </button> <button v-if="shouldShowDeleteButton" - class="btn btn-danger pull-right append-right-default" + class="btn btn-danger float-right append-right-default" :class="{ disabled: deleteLoading }" type="button" :disabled="deleteLoading" diff --git a/app/assets/javascripts/issue_show/components/form.vue b/app/assets/javascripts/issue_show/components/form.vue index 779705e19ac..ab8bd34762f 100644 --- a/app/assets/javascripts/issue_show/components/form.vue +++ b/app/assets/javascripts/issue_show/components/form.vue @@ -84,7 +84,7 @@ <div :class="{ 'col-sm-8 col-lg-9': hasIssuableTemplates, - 'col-xs-12': !hasIssuableTemplates, + 'col-12': !hasIssuableTemplates, }" > <title-field diff --git a/app/assets/javascripts/job.js b/app/assets/javascripts/job.js index ace45e9dd29..c67bd7fb0c6 100644 --- a/app/assets/javascripts/job.js +++ b/app/assets/javascripts/job.js @@ -1,5 +1,6 @@ import $ from 'jquery'; import _ from 'underscore'; +import StickyFill from 'stickyfilljs'; import axios from './lib/utils/axios_utils'; import { visitUrl } from './lib/utils/url_utility'; import bp from './breakpoints'; @@ -82,17 +83,11 @@ export default class Job { /** If the browser does not support position sticky, it returns the position as static. If the browser does support sticky, then we allow the browser to handle it, if not - then we default back to Bootstraps affix + then we use a polyfill **/ if (this.$topBar.css('position') !== 'static') return; - const offsetTop = this.$buildTrace.offset().top; - - this.$topBar.affix({ - offset: { - top: offsetTop, - }, - }); + StickyFill.add(this.$topBar); } // eslint-disable-next-line class-methods-use-this diff --git a/app/assets/javascripts/jobs/components/header.vue b/app/assets/javascripts/jobs/components/header.vue index 21b545d6cab..c1044f4cd42 100644 --- a/app/assets/javascripts/jobs/components/header.vue +++ b/app/assets/javascripts/jobs/components/header.vue @@ -56,7 +56,7 @@ export default { actions.push({ label: 'New issue', path: this.job.new_issue_path, - cssClass: 'js-new-issue btn btn-new btn-inverted visible-md-block visible-lg-block', + cssClass: 'js-new-issue btn btn-new btn-inverted d-none d-md-block d-lg-block d-xl-block', type: 'link', }); } diff --git a/app/assets/javascripts/jobs/components/sidebar_detail_row.vue b/app/assets/javascripts/jobs/components/sidebar_detail_row.vue index dfe87d89a39..83560a8ff0e 100644 --- a/app/assets/javascripts/jobs/components/sidebar_detail_row.vue +++ b/app/assets/javascripts/jobs/components/sidebar_detail_row.vue @@ -39,7 +39,7 @@ <span v-if="hasHelpURL" - class="help-button pull-right" + class="help-button float-right" > <a :href="helpUrl" diff --git a/app/assets/javascripts/jobs/components/sidebar_details_block.vue b/app/assets/javascripts/jobs/components/sidebar_details_block.vue index db19dc9b238..82fec7e936b 100644 --- a/app/assets/javascripts/jobs/components/sidebar_details_block.vue +++ b/app/assets/javascripts/jobs/components/sidebar_details_block.vue @@ -48,7 +48,7 @@ export default { return `${this.job.runner.description} (#${this.job.runner.id})`; }, retryButtonClass() { - let className = 'js-retry-button pull-right btn btn-retry visible-md-block visible-lg-block'; + let className = 'js-retry-button pull-right btn btn-retry d-none d-md-block d-lg-block d-xl-block'; className += this.job.status && this.job.recoverable ? ' btn-primary' @@ -105,7 +105,7 @@ export default { type="button" :aria-label="__('Toggle Sidebar')" class="btn btn-blank gutter-toggle pull-right - visible-xs-block visible-sm-block js-sidebar-build-toggle" + d-block d-sm-block d-md-none js-sidebar-build-toggle" > <i aria-hidden="true" diff --git a/app/assets/javascripts/label_manager.js b/app/assets/javascripts/label_manager.js index e230dbbd4ac..6af22ecc990 100644 --- a/app/assets/javascripts/label_manager.js +++ b/app/assets/javascripts/label_manager.js @@ -35,7 +35,7 @@ export default class LabelManager { const $label = $(`#${$btn.data('domId')}`); const action = $btn.parents('.js-prioritized-labels').length ? 'remove' : 'add'; const $tooltip = $(`#${$btn.find('.has-tooltip:visible').attr('aria-describedby')}`); - $tooltip.tooltip('destroy'); + $tooltip.tooltip('dispose'); _this.toggleLabelPriority($label, action); _this.toggleEmptyState($label, $btn, action); } diff --git a/app/assets/javascripts/labels_select.js b/app/assets/javascripts/labels_select.js index 9b62cfb8206..eafdaf4a672 100644 --- a/app/assets/javascripts/labels_select.js +++ b/app/assets/javascripts/labels_select.js @@ -120,7 +120,7 @@ export default class LabelsSelect { $sidebarLabelTooltip .attr('title', labelTooltipTitle) - .tooltip('fixTitle'); + .tooltip('_fixTitle'); $('.has-tooltip', $value).tooltip({ container: 'body' diff --git a/app/assets/javascripts/lib/utils/common_utils.js b/app/assets/javascripts/lib/utils/common_utils.js index 9ff2042475b..8b5445d012b 100644 --- a/app/assets/javascripts/lib/utils/common_utils.js +++ b/app/assets/javascripts/lib/utils/common_utils.js @@ -51,7 +51,7 @@ export const rstrip = (val) => { return val; }; -export const updateTooltipTitle = ($tooltipEl, newTitle) => $tooltipEl.attr('title', newTitle).tooltip('fixTitle'); +export const updateTooltipTitle = ($tooltipEl, newTitle) => $tooltipEl.attr('title', newTitle).tooltip('_fixTitle'); export const disableButtonIfEmptyField = (fieldSelector, buttonSelector, eventName = 'input') => { const field = $(fieldSelector); diff --git a/app/assets/javascripts/lib/utils/datetime_utility.js b/app/assets/javascripts/lib/utils/datetime_utility.js index c3d94d63c13..0ff23bbb061 100644 --- a/app/assets/javascripts/lib/utils/datetime_utility.js +++ b/app/assets/javascripts/lib/utils/datetime_utility.js @@ -2,10 +2,7 @@ import $ from 'jquery'; import timeago from 'timeago.js'; import dateFormat from 'vendor/date.format'; import { pluralize } from './text_utility'; -import { - languageCode, - s__, -} from '../../locale'; +import { languageCode, s__ } from '../../locale'; window.timeago = timeago; window.dateFormat = dateFormat; @@ -17,11 +14,37 @@ window.dateFormat = dateFormat; * * @param {Boolean} abbreviated */ -const getMonthNames = (abbreviated) => { +const getMonthNames = abbreviated => { if (abbreviated) { - return [s__('Jan'), s__('Feb'), s__('Mar'), s__('Apr'), s__('May'), s__('Jun'), s__('Jul'), s__('Aug'), s__('Sep'), s__('Oct'), s__('Nov'), s__('Dec')]; + return [ + s__('Jan'), + s__('Feb'), + s__('Mar'), + s__('Apr'), + s__('May'), + s__('Jun'), + s__('Jul'), + s__('Aug'), + s__('Sep'), + s__('Oct'), + s__('Nov'), + s__('Dec'), + ]; } - return [s__('January'), s__('February'), s__('March'), s__('April'), s__('May'), s__('June'), s__('July'), s__('August'), s__('September'), s__('October'), s__('November'), s__('December')]; + return [ + s__('January'), + s__('February'), + s__('March'), + s__('April'), + s__('May'), + s__('June'), + s__('July'), + s__('August'), + s__('September'), + s__('October'), + s__('November'), + s__('December'), + ]; }; /** @@ -29,7 +52,8 @@ const getMonthNames = (abbreviated) => { * @param {date} date * @returns {String} */ -export const getDayName = date => ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'][date.getDay()]; +export const getDayName = date => + ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'][date.getDay()]; /** * @example @@ -55,7 +79,7 @@ export function getTimeago() { if (!timeagoInstance) { const localeRemaining = function getLocaleRemaining(number, index) { return [ - [s__('Timeago|less than a minute ago'), s__('Timeago|in a while')], + [s__('Timeago|less than a minute ago'), s__('Timeago|right now')], [s__('Timeago|less than a minute ago'), s__('Timeago|%s seconds remaining')], [s__('Timeago|about a minute ago'), s__('Timeago|1 minute remaining')], [s__('Timeago|%s minutes ago'), s__('Timeago|%s minutes remaining')], @@ -73,7 +97,7 @@ export function getTimeago() { }; const locale = function getLocale(number, index) { return [ - [s__('Timeago|less than a minute ago'), s__('Timeago|in a while')], + [s__('Timeago|less than a minute ago'), s__('Timeago|right now')], [s__('Timeago|less than a minute ago'), s__('Timeago|in %s seconds')], [s__('Timeago|about a minute ago'), s__('Timeago|in 1 minute')], [s__('Timeago|%s minutes ago'), s__('Timeago|in %s minutes')], @@ -102,7 +126,7 @@ export function getTimeago() { * For the given element, renders a timeago instance. * @param {jQuery} $els */ -export const renderTimeago = ($els) => { +export const renderTimeago = $els => { const timeagoEls = $els || document.querySelectorAll('.js-timeago-render'); // timeago.js sets timeouts internally for each timeago value to be updated in real time @@ -119,7 +143,7 @@ export const localTimeAgo = ($timeagoEls, setTimeago = true) => { if (setTimeago) { // Recreate with custom template $(el).tooltip({ - template: '<div class="tooltip local-timeago" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>', + template: '<div class="tooltip local-timeago" role="tooltip"><div class="arrow"></div><div class="tooltip-inner"></div></div>', }); } @@ -141,7 +165,9 @@ export const timeFor = (time, expiredLabel) => { if (new Date(time) < new Date()) { return expiredLabel || s__('Timeago|Past due'); } - return getTimeago().format(time, `${timeagoLanguageCode}-remaining`).trim(); + return getTimeago() + .format(time, `${timeagoLanguageCode}-remaining`) + .trim(); }; export const getDayDifference = (a, b) => { @@ -161,7 +187,7 @@ export const getDayDifference = (a, b) => { export function timeIntervalInWords(intervalInSeconds) { const secondsInteger = parseInt(intervalInSeconds, 10); const minutes = Math.floor(secondsInteger / 60); - const seconds = secondsInteger - (minutes * 60); + const seconds = secondsInteger - minutes * 60; let text = ''; if (minutes >= 1) { @@ -178,8 +204,34 @@ export function dateInWords(date, abbreviated = false, hideYear = false) { const month = date.getMonth(); const year = date.getFullYear(); - const monthNames = [s__('January'), s__('February'), s__('March'), s__('April'), s__('May'), s__('June'), s__('July'), s__('August'), s__('September'), s__('October'), s__('November'), s__('December')]; - const monthNamesAbbr = [s__('Jan'), s__('Feb'), s__('Mar'), s__('Apr'), s__('May'), s__('Jun'), s__('Jul'), s__('Aug'), s__('Sep'), s__('Oct'), s__('Nov'), s__('Dec')]; + const monthNames = [ + s__('January'), + s__('February'), + s__('March'), + s__('April'), + s__('May'), + s__('June'), + s__('July'), + s__('August'), + s__('September'), + s__('October'), + s__('November'), + s__('December'), + ]; + const monthNamesAbbr = [ + s__('Jan'), + s__('Feb'), + s__('Mar'), + s__('Apr'), + s__('May'), + s__('Jun'), + s__('Jul'), + s__('Aug'), + s__('Sep'), + s__('Oct'), + s__('Nov'), + s__('Dec'), + ]; const monthName = abbreviated ? monthNamesAbbr[month] : monthNames[month]; @@ -210,7 +262,7 @@ export const monthInWords = (date, abbreviated = false) => { * * @param {Date} date */ -export const totalDaysInMonth = (date) => { +export const totalDaysInMonth = date => { if (!date) { return 0; } @@ -223,12 +275,20 @@ export const totalDaysInMonth = (date) => { * * @param {Date} date */ -export const getSundays = (date) => { +export const getSundays = date => { if (!date) { return []; } - const daysToSunday = ['Saturday', 'Friday', 'Thursday', 'Wednesday', 'Tuesday', 'Monday', 'Sunday']; + const daysToSunday = [ + 'Saturday', + 'Friday', + 'Thursday', + 'Wednesday', + 'Tuesday', + 'Monday', + 'Sunday', + ]; const month = date.getMonth(); const year = date.getFullYear(); diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js index 247aeb481c6..9803bebfd10 100644 --- a/app/assets/javascripts/main.js +++ b/app/assets/javascripts/main.js @@ -46,9 +46,9 @@ document.addEventListener('beforeunload', () => { // Unbind scroll events $(document).off('scroll'); // Close any open tooltips - $('.has-tooltip, [data-toggle="tooltip"]').tooltip('destroy'); + $('.has-tooltip, [data-toggle="tooltip"]').tooltip('dispose'); // Close any open popover - $('[data-toggle="popover"]').popover('destroy'); + $('[data-toggle="popover"]').popover('dispose'); }); window.addEventListener('hashchange', handleLocationHash); @@ -111,7 +111,7 @@ document.addEventListener('DOMContentLoaded', () => { $('.remove-row').on('ajax:success', function removeRowAjaxSuccessCallback() { $(this) - .tooltip('destroy') + .tooltip('dispose') .closest('li') .fadeOut(); }); @@ -141,9 +141,9 @@ document.addEventListener('DOMContentLoaded', () => { }); // Initialize tooltips - $.fn.tooltip.Constructor.DEFAULTS.trigger = 'hover'; $body.tooltip({ selector: '.has-tooltip, [data-toggle="tooltip"]', + trigger: 'hover', placement(tip, el) { return $(el).data('placement') || 'bottom'; }, @@ -196,7 +196,7 @@ document.addEventListener('DOMContentLoaded', () => { $container.remove(); }); - $('.navbar-toggle').on('click', () => { + $('.navbar-toggler').on('click', () => { $('.header-content').toggleClass('menu-expanded'); gl.lazyLoader.loadCheck(); }); diff --git a/app/assets/javascripts/merge_conflicts/merge_conflict_store.js b/app/assets/javascripts/merge_conflicts/merge_conflict_store.js index db1d09eb2f2..70f185e3656 100644 --- a/app/assets/javascripts/merge_conflicts/merge_conflict_store.js +++ b/app/assets/javascripts/merge_conflicts/merge_conflict_store.js @@ -351,7 +351,7 @@ import Cookies from 'js-cookie'; }, getCommitButtonText() { - const initial = 'Commit conflict resolution'; + const initial = 'Commit to source branch'; const inProgress = 'Committing...'; return this.state ? this.state.isSubmitting ? inProgress : initial : initial; diff --git a/app/assets/javascripts/merge_request_tabs.js b/app/assets/javascripts/merge_request_tabs.js index 3f84f4b9499..3548c07aea8 100644 --- a/app/assets/javascripts/merge_request_tabs.js +++ b/app/assets/javascripts/merge_request_tabs.js @@ -362,7 +362,7 @@ export default class MergeRequestTabs { // // status - Boolean, true to show, false to hide toggleLoading(status) { - $('.mr-loading-status .loading').toggle(status); + $('.mr-loading-status .loading').toggleClass('hidden', status); } diffViewType() { diff --git a/app/assets/javascripts/monitoring/components/graph_group.vue b/app/assets/javascripts/monitoring/components/graph_group.vue index a6dbe42a8f0..241627f9790 100644 --- a/app/assets/javascripts/monitoring/components/graph_group.vue +++ b/app/assets/javascripts/monitoring/components/graph_group.vue @@ -17,12 +17,12 @@ export default { <template> <div v-if="showPanels" - class="panel panel-default prometheus-panel" + class="card prometheus-panel" > - <div class="panel-heading"> + <div class="card-header"> <h4>{{ name }}</h4> </div> - <div class="panel-body prometheus-graph-group"> + <div class="card-body prometheus-graph-group"> <slot></slot> </div> </div> diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js index 96f2b3eac98..b2c1a26bbae 100644 --- a/app/assets/javascripts/notes.js +++ b/app/assets/javascripts/notes.js @@ -1231,8 +1231,8 @@ export default class Notes { const isForced = forceShow === true || forceShow === false; const showNow = forceShow === true || (!isCurrentlyShown && !isForced); - targetRow.toggle(showNow); - notesContent.toggle(showNow); + targetRow.toggleClass('hide', !showNow); + notesContent.toggleClass('hide', !showNow); } if (addForm) { @@ -1675,7 +1675,7 @@ export default class Notes { <div class="note-header"> <div class="note-header-info"> <a href="/${_.escape(currentUsername)}"> - <span class="hidden-xs">${_.escape( + <span class="d-none d-sm-block">${_.escape( currentUsername, )}</span> <span class="note-headline-light">${_.escape( @@ -1694,7 +1694,7 @@ export default class Notes { </li>`, ); - $tempNote.find('.hidden-xs').text(_.escape(currentUserFullname)); + $tempNote.find('.d-none.d-sm-block').text(_.escape(currentUserFullname)); $tempNote .find('.note-headline-light') .text(`@${_.escape(currentUsername)}`); diff --git a/app/assets/javascripts/notes/components/comment_form.vue b/app/assets/javascripts/notes/components/comment_form.vue index 48642c4a086..72d7e22fba0 100644 --- a/app/assets/javascripts/notes/components/comment_form.vue +++ b/app/assets/javascripts/notes/components/comment_form.vue @@ -321,7 +321,7 @@ Please check your network connection and try again.`; <li class="timeline-entry"> <div class="timeline-entry-inner"> <div class="flash-container error-alert timeline-content"></div> - <div class="timeline-icon hidden-xs hidden-sm"> + <div class="timeline-icon d-none d-sm-none d-md-block"> <user-avatar-link v-if="author" :link-href="author.path" @@ -369,7 +369,7 @@ js-gfm-input js-autosize markdown-area js-vue-textarea" </markdown-field> <div class="note-form-actions"> <div - class="pull-left btn-group + class="float-left btn-group append-right-10 comment-type-dropdown js-comment-type-dropdown droplab-dropdown"> <button @click.prevent="handleSave()" @@ -383,6 +383,7 @@ append-right-10 comment-type-dropdown js-comment-type-dropdown droplab-dropdown" name="button" type="button" class="btn comment-btn note-type-toggle js-note-new-discussion dropdown-toggle" + data-display="static" data-toggle="dropdown" aria-label="Open comment type dropdown"> <i diff --git a/app/assets/javascripts/notes/components/note_edited_text.vue b/app/assets/javascripts/notes/components/note_edited_text.vue index 4ddca918495..2dc39d1a186 100644 --- a/app/assets/javascripts/notes/components/note_edited_text.vue +++ b/app/assets/javascripts/notes/components/note_edited_text.vue @@ -32,17 +32,17 @@ export default { <template> <div :class="className"> {{ actionText }} - <time-ago-tooltip - :time="editedAt" - tooltip-placement="bottom" - /> <template v-if="editedBy"> - by + {{ s__('ByAuthor|by') }} <a :href="editedBy.path" class="js-vue-author author_link"> {{ editedBy.name }} </a> </template> + <time-ago-tooltip + :time="editedAt" + tooltip-placement="bottom" + /> </div> </template> diff --git a/app/assets/javascripts/notes/components/note_header.vue b/app/assets/javascripts/notes/components/note_header.vue index c3d1ef1fcc6..a4081957207 100644 --- a/app/assets/javascripts/notes/components/note_header.vue +++ b/app/assets/javascripts/notes/components/note_header.vue @@ -62,6 +62,21 @@ export default { <template> <div class="note-header-info"> + <div + v-if="includeToggle" + class="discussion-actions"> + <button + @click="handleToggle" + class="note-action-button discussion-toggle-button js-vue-toggle-button" + type="button"> + <i + :class="toggleChevronClass" + class="fa" + aria-hidden="true"> + </i> + {{ __('Toggle discussion') }} + </button> + </div> <a :href="author.path"> <span class="note-header-author-name">{{ author.name }}</span> <span class="note-headline-light"> @@ -78,10 +93,13 @@ export default { v-html="actionTextHtml" class="system-note-message"> </span> + <span class="system-note-separator"> + · + </span> <a :href="noteTimestampLink" @click="updateTargetNoteHash" - class="note-timestamp"> + class="note-timestamp system-note-separator"> <time-ago-tooltip :time="createdAt" tooltip-placement="bottom" @@ -95,20 +113,5 @@ export default { </i> </span> </span> - <div - v-if="includeToggle" - class="discussion-actions"> - <button - @click="handleToggle" - class="note-action-button discussion-toggle-button js-vue-toggle-button" - type="button"> - <i - :class="toggleChevronClass" - class="fa" - aria-hidden="true"> - </i> - Toggle discussion - </button> - </div> </div> </template> diff --git a/app/assets/javascripts/notes/components/noteable_discussion.vue b/app/assets/javascripts/notes/components/noteable_discussion.vue index e0f883a8e08..7f5aacaa3a2 100644 --- a/app/assets/javascripts/notes/components/noteable_discussion.vue +++ b/app/assets/javascripts/notes/components/noteable_discussion.vue @@ -100,7 +100,7 @@ export default { : 'div'; }, wrapperClass() { - return this.isDiffDiscussion ? '' : 'panel panel-default'; + return this.isDiffDiscussion ? '' : 'card'; }, }, mounted() { @@ -263,7 +263,7 @@ Please check your network connection and try again.`; class="discussion-reply-holder"> <template v-if="!isReplying && canReply"> <div - class="btn-group-justified discussion-with-resolve-btn" + class="btn-group d-flex discussion-with-resolve-btn" role="group"> <div class="btn-group" diff --git a/app/assets/javascripts/notifications_form.js b/app/assets/javascripts/notifications_form.js index 9e6cf67dff0..00e27ca0e70 100644 --- a/app/assets/javascripts/notifications_form.js +++ b/app/assets/javascripts/notifications_form.js @@ -15,7 +15,7 @@ export default class NotificationsForm { toggleCheckbox(e) { const $checkbox = $(e.currentTarget); - const $parent = $checkbox.closest('.checkbox'); + const $parent = $checkbox.closest('.form-check'); this.saveEvent($checkbox, $parent); } diff --git a/app/assets/javascripts/pages/admin/admin.js b/app/assets/javascripts/pages/admin/admin.js index 91f154b7ecd..ff4d6ab15f9 100644 --- a/app/assets/javascripts/pages/admin/admin.js +++ b/app/assets/javascripts/pages/admin/admin.js @@ -25,7 +25,7 @@ export default function adminInit() { $('body').on('click', '.js-toggle-colors-link', (e) => { e.preventDefault(); - $('.js-toggle-colors-container').toggle(); + $('.js-toggle-colors-container').toggleClass('hide'); }); $('.log-tabs a').on('click', function logTabsClick(e) { diff --git a/app/assets/javascripts/pages/ldap/omniauth_callbacks/index.js b/app/assets/javascripts/pages/ldap/omniauth_callbacks/index.js new file mode 100644 index 00000000000..edd7e38471b --- /dev/null +++ b/app/assets/javascripts/pages/ldap/omniauth_callbacks/index.js @@ -0,0 +1,3 @@ +import initU2F from '../../../shared/sessions/u2f'; + +document.addEventListener('DOMContentLoaded', initU2F); diff --git a/app/assets/javascripts/pages/profiles/two_factor_auths/index.js b/app/assets/javascripts/pages/profiles/two_factor_auths/index.js index fbdef329ab2..8e8f47c21d8 100644 --- a/app/assets/javascripts/pages/profiles/two_factor_auths/index.js +++ b/app/assets/javascripts/pages/profiles/two_factor_auths/index.js @@ -5,7 +5,7 @@ document.addEventListener('DOMContentLoaded', () => { const twoFactorNode = document.querySelector('.js-two-factor-auth'); const skippable = twoFactorNode.dataset.twoFactorSkippable === 'true'; if (skippable) { - const button = `<a class="btn btn-xs btn-warning pull-right" data-method="patch" href="${twoFactorNode.dataset.two_factor_skip_url}">Configure it later</a>`; + const button = `<a class="btn btn-sm btn-warning float-right" data-method="patch" href="${twoFactorNode.dataset.two_factor_skip_url}">Configure it later</a>`; const flashAlert = document.querySelector('.flash-alert .container-fluid'); if (flashAlert) flashAlert.insertAdjacentHTML('beforeend', button); } diff --git a/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js b/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js index a99ce0f1c36..5316d3e9f3c 100644 --- a/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js +++ b/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js @@ -1,4 +1,4 @@ -/* eslint-disable func-names, space-before-function-paren, no-var, prefer-rest-params, max-len, no-restricted-syntax, vars-on-top, no-use-before-define, no-param-reassign, new-cap, no-underscore-dangle, wrap-iife, comma-dangle, no-return-assign, prefer-arrow-callback, quotes, prefer-template, newline-per-chained-call, no-else-return, no-shadow */ +/* eslint-disable func-names, space-before-function-paren, prefer-rest-params, max-len, no-restricted-syntax, vars-on-top, no-use-before-define, no-param-reassign, new-cap, no-underscore-dangle, wrap-iife, comma-dangle, no-return-assign, prefer-arrow-callback, quotes, prefer-template, newline-per-chained-call, no-else-return, no-shadow */ import $ from 'jquery'; import _ from 'underscore'; @@ -13,17 +13,17 @@ import { dateTickFormat } from '~/lib/utils/tick_formats'; const d3 = { extent, max, select, scaleTime, scaleLinear, axisLeft, axisBottom, area, brushX, timeParse }; -const extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; const hasProp = {}.hasOwnProperty; +const extend = function(child, parent) { for (const key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; export const ContributorsGraph = (function() { function ContributorsGraph() {} ContributorsGraph.prototype.MARGIN = { top: 20, - right: 20, + right: 10, bottom: 30, - left: 50 + left: 40 }; ContributorsGraph.prototype.x_domain = null; @@ -32,6 +32,12 @@ export const ContributorsGraph = (function() { ContributorsGraph.prototype.dates = []; + ContributorsGraph.prototype.determine_width = function(baseWidth, $parentElement) { + const parentPaddingWidth = parseFloat($parentElement.css('padding-left')) + parseFloat($parentElement.css('padding-right')); + const marginWidth = this.MARGIN.left + this.MARGIN.right; + return baseWidth - parentPaddingWidth - marginWidth; + }; + ContributorsGraph.set_x_domain = function(data) { return ContributorsGraph.prototype.x_domain = data; }; @@ -105,11 +111,10 @@ export const ContributorsMasterGraph = (function(superClass) { function ContributorsMasterGraph(data1) { const $parentElement = $('#contributors-master'); - const parentPadding = parseFloat($parentElement.css('padding-left')) + parseFloat($parentElement.css('padding-right')); this.data = data1; this.update_content = this.update_content.bind(this); - this.width = $('.content').width() - parentPadding - (this.MARGIN.left + this.MARGIN.right); + this.width = this.determine_width($('.js-graphs-show').width(), $parentElement); this.height = 200; this.x = null; this.y = null; @@ -122,8 +127,7 @@ export const ContributorsMasterGraph = (function(superClass) { } ContributorsMasterGraph.prototype.process_dates = function(data) { - var dates; - dates = this.get_dates(data); + const dates = this.get_dates(data); this.parse_dates(data); return ContributorsGraph.set_dates(dates); }; @@ -133,8 +137,7 @@ export const ContributorsMasterGraph = (function(superClass) { }; ContributorsMasterGraph.prototype.parse_dates = function(data) { - var parseDate; - parseDate = d3.timeParse("%Y-%m-%d"); + const parseDate = d3.timeParse("%Y-%m-%d"); return data.forEach(function(d) { return d.date = parseDate(d.date); }); @@ -152,7 +155,14 @@ export const ContributorsMasterGraph = (function(superClass) { }; ContributorsMasterGraph.prototype.create_svg = function() { - return this.svg = d3.select("#contributors-master").append("svg").attr("width", this.width + this.MARGIN.left + this.MARGIN.right).attr("height", this.height + this.MARGIN.top + this.MARGIN.bottom).attr("class", "tint-box").append("g").attr("transform", "translate(" + this.MARGIN.left + "," + this.MARGIN.top + ")"); + this.svg = d3.select("#contributors-master") + .append("svg") + .attr("width", this.width + this.MARGIN.left + this.MARGIN.right) + .attr("height", this.height + this.MARGIN.top + this.MARGIN.bottom) + .attr("class", "tint-box") + .append("g") + .attr("transform", "translate(" + this.MARGIN.left + "," + this.MARGIN.top + ")"); + return this.svg; }; ContributorsMasterGraph.prototype.create_area = function(x, y) { @@ -218,12 +228,14 @@ export const ContributorsAuthorGraph = (function(superClass) { extend(ContributorsAuthorGraph, superClass); function ContributorsAuthorGraph(data1) { + const $parentElements = $('.person'); + this.data = data1; // Don't split graph size in half for mobile devices. - if ($(window).width() < 768) { - this.width = $('.content').width() - 80; + if ($(window).width() < 790) { + this.width = this.determine_width($('.js-graphs-show').width(), $parentElements); } else { - this.width = ($('.content').width() / 2) - 100; + this.width = this.determine_width($('.js-graphs-show').width() / 2, $parentElements); } this.height = 200; this.x = null; @@ -249,8 +261,7 @@ export const ContributorsAuthorGraph = (function(superClass) { ContributorsAuthorGraph.prototype.create_area = function(x, y) { return this.area = d3.area().x(function(d) { - var parseDate; - parseDate = d3.timeParse("%Y-%m-%d"); + const parseDate = d3.timeParse("%Y-%m-%d"); return x(parseDate(d)); }).y0(this.height).y1((function(_this) { return function(d) { @@ -264,9 +275,16 @@ export const ContributorsAuthorGraph = (function(superClass) { }; ContributorsAuthorGraph.prototype.create_svg = function() { - var persons = document.querySelectorAll('.person'); + const persons = document.querySelectorAll('.person'); this.list_item = persons[persons.length - 1]; - return this.svg = d3.select(this.list_item).append("svg").attr("width", this.width + this.MARGIN.left + this.MARGIN.right).attr("height", this.height + this.MARGIN.top + this.MARGIN.bottom).attr("class", "spark").append("g").attr("transform", "translate(" + this.MARGIN.left + "," + this.MARGIN.top + ")"); + this.svg = d3.select(this.list_item) + .append("svg") + .attr("width", this.width + this.MARGIN.left + this.MARGIN.right) + .attr("height", this.height + this.MARGIN.top + this.MARGIN.bottom) + .attr("class", "spark") + .append("g") + .attr("transform", "translate(" + this.MARGIN.left + "," + this.MARGIN.top + ")"); + return this.svg; }; ContributorsAuthorGraph.prototype.draw_path = function(data) { diff --git a/app/assets/javascripts/pages/projects/shared/permissions/components/project_setting_row.vue b/app/assets/javascripts/pages/projects/shared/permissions/components/project_setting_row.vue index 25a88f846eb..17b91479ea5 100644 --- a/app/assets/javascripts/pages/projects/shared/permissions/components/project_setting_row.vue +++ b/app/assets/javascripts/pages/projects/shared/permissions/components/project_setting_row.vue @@ -42,7 +42,7 @@ </label> <span v-if="helpText" - class="help-block" + class="form-text text-muted" > {{ helpText }} </span> diff --git a/app/assets/javascripts/pages/projects/wikis/components/delete_wiki_modal.vue b/app/assets/javascripts/pages/projects/wikis/components/delete_wiki_modal.vue new file mode 100644 index 00000000000..df21e2f8771 --- /dev/null +++ b/app/assets/javascripts/pages/projects/wikis/components/delete_wiki_modal.vue @@ -0,0 +1,77 @@ +<script> +import _ from 'underscore'; +import GlModal from '~/vue_shared/components/gl_modal.vue'; +import { s__, sprintf } from '~/locale'; + +export default { + components: { + GlModal, + }, + props: { + deleteWikiUrl: { + type: String, + required: true, + default: '', + }, + pageTitle: { + type: String, + required: true, + default: '', + }, + csrfToken: { + type: String, + required: true, + default: '', + }, + }, + computed: { + message() { + return s__('WikiPageConfirmDelete|Are you sure you want to delete this page?'); + }, + title() { + return sprintf( + s__('WikiPageConfirmDelete|Delete page %{pageTitle}?'), + { + pageTitle: _.escape(this.pageTitle), + }, + false, + ); + }, + }, + methods: { + onSubmit() { + this.$refs.form.submit(); + }, + }, +}; +</script> + +<template> + <gl-modal + id="delete-wiki-modal" + :header-title-text="title" + footer-primary-button-variant="danger" + :footer-primary-button-text="s__('WikiPageConfirmDelete|Delete page')" + @submit="onSubmit" + > + {{ message }} + <form + ref="form" + :action="deleteWikiUrl" + method="post" + class="form-horizontal js-requires-input" + > + <input + ref="method" + type="hidden" + name="_method" + value="delete" + /> + <input + type="hidden" + name="authenticity_token" + :value="csrfToken" + /> + </form> + </gl-modal> +</template> diff --git a/app/assets/javascripts/pages/projects/wikis/index.js b/app/assets/javascripts/pages/projects/wikis/index.js index ec01c66ffda..0295653cb29 100644 --- a/app/assets/javascripts/pages/projects/wikis/index.js +++ b/app/assets/javascripts/pages/projects/wikis/index.js @@ -1,12 +1,40 @@ import $ from 'jquery'; +import Vue from 'vue'; +import Translate from '~/vue_shared/translate'; +import csrf from '~/lib/utils/csrf'; import Wikis from './wikis'; import ShortcutsWiki from '../../../shortcuts_wiki'; import ZenMode from '../../../zen_mode'; import GLForm from '../../../gl_form'; +import deleteWikiModal from './components/delete_wiki_modal.vue'; document.addEventListener('DOMContentLoaded', () => { new Wikis(); // eslint-disable-line no-new new ShortcutsWiki(); // eslint-disable-line no-new new ZenMode(); // eslint-disable-line no-new new GLForm($('.wiki-form'), true); // eslint-disable-line no-new + + const deleteWikiButton = document.getElementById('delete-wiki-button'); + + if (deleteWikiButton) { + Vue.use(Translate); + + const { deleteWikiUrl, pageTitle } = deleteWikiButton.dataset; + const deleteWikiModalEl = document.getElementById('delete-wiki-modal'); + const deleteModal = new Vue({ // eslint-disable-line + el: deleteWikiModalEl, + data: { + deleteWikiUrl: '', + }, + render(createElement) { + return createElement(deleteWikiModal, { + props: { + pageTitle, + deleteWikiUrl, + csrfToken: csrf.token, + }, + }); + }, + }); + } }); diff --git a/app/assets/javascripts/pages/users/user_tabs.js b/app/assets/javascripts/pages/users/user_tabs.js index 124bc2ba710..ca375007ec5 100644 --- a/app/assets/javascripts/pages/users/user_tabs.js +++ b/app/assets/javascripts/pages/users/user_tabs.js @@ -181,7 +181,7 @@ export default class UserTabs { toggleLoading(status) { return this.$parentEl.find('.loading-status .loading') - .toggle(status); + .toggleClass('hidden', status); } setCurrentAction(source) { @@ -195,6 +195,6 @@ export default class UserTabs { } getCurrentAction() { - return this.$parentEl.find('.nav-links .active a').data('action'); + return this.$parentEl.find('.nav-links a.active').data('action'); } } diff --git a/app/assets/javascripts/performance_bar/components/request_selector.vue b/app/assets/javascripts/performance_bar/components/request_selector.vue index 3ed07a4a47d..dd9578a6c7f 100644 --- a/app/assets/javascripts/performance_bar/components/request_selector.vue +++ b/app/assets/javascripts/performance_bar/components/request_selector.vue @@ -37,7 +37,7 @@ export default { <template> <div id="peek-request-selector" - class="pull-right" + class="float-right" > <select v-model="currentRequestId"> <option diff --git a/app/assets/javascripts/pipelines/components/blank_state.vue b/app/assets/javascripts/pipelines/components/blank_state.vue index 8d3d6223d7b..f3219b8291c 100644 --- a/app/assets/javascripts/pipelines/components/blank_state.vue +++ b/app/assets/javascripts/pipelines/components/blank_state.vue @@ -17,13 +17,13 @@ <template> <div class="row empty-state"> - <div class="col-xs-12"> + <div class="col-12"> <div class="svg-content"> <img :src="svgPath" /> </div> </div> - <div class="col-xs-12 text-center"> + <div class="col-12 text-center"> <div class="text-content"> <h4>{{ message }}</h4> </div> diff --git a/app/assets/javascripts/pipelines/components/empty_state.vue b/app/assets/javascripts/pipelines/components/empty_state.vue index 10ac8c08bed..50c27bed9fd 100644 --- a/app/assets/javascripts/pipelines/components/empty_state.vue +++ b/app/assets/javascripts/pipelines/components/empty_state.vue @@ -19,13 +19,13 @@ </script> <template> <div class="row empty-state js-empty-state"> - <div class="col-xs-12"> + <div class="col-12"> <div class="svg-content svg-250"> <img :src="emptyStateSvgPath" /> </div> </div> - <div class="col-xs-12"> + <div class="col-12"> <div class="text-content"> <template v-if="canSetCi"> @@ -34,7 +34,7 @@ </h4> <p> - {{ s__(`Pipelines|Continous Integration can help + {{ s__(`Pipelines|Continuous Integration can help catch bugs by running your tests automatically, while Continuous Deployment can help you deliver code to your product environment.`) }} diff --git a/app/assets/javascripts/pipelines/components/graph/action_component.vue b/app/assets/javascripts/pipelines/components/graph/action_component.vue index fd3491c7fe0..82b4ce083fb 100644 --- a/app/assets/javascripts/pipelines/components/graph/action_component.vue +++ b/app/assets/javascripts/pipelines/components/graph/action_component.vue @@ -1,11 +1,21 @@ <script> import $ from 'jquery'; -import tooltip from '../../../vue_shared/directives/tooltip'; -import Icon from '../../../vue_shared/components/icon.vue'; -import { dasherize } from '../../../lib/utils/text_utility'; -import eventHub from '../../event_hub'; +import axios from '~/lib/utils/axios_utils'; +import { dasherize } from '~/lib/utils/text_utility'; +import { __ } from '~/locale'; +import createFlash from '~/flash'; +import tooltip from '~/vue_shared/directives/tooltip'; +import Icon from '~/vue_shared/components/icon.vue'; + /** - * Renders either a cancel, retry or play icon pointing to the given path. + * Renders either a cancel, retry or play icon button and handles the post request + * + * Used in: + * - mr widget mini pipeline graph: `mr_widget_pipeline.vue` + * - pipelines table + * - pipelines table in merge request page + * - pipelines table in commit page + * - pipelines detail page in big graph */ export default { components: { @@ -32,16 +42,10 @@ export default { required: true, }, - requestFinishedFor: { - type: String, - required: false, - default: '', - }, }, data() { return { isDisabled: false, - linkRequested: '', }; }, @@ -51,19 +55,28 @@ export default { return `${actionIconDash} js-icon-${actionIconDash}`; }, }, - watch: { - requestFinishedFor() { - if (this.requestFinishedFor === this.linkRequested) { - this.isDisabled = false; - } - }, - }, methods: { + /** + * The request should not be handled here. + * However due to this component being used in several + * different apps it avoids repetition & complexity. + * + */ onClickAction() { $(this.$el).tooltip('hide'); - eventHub.$emit('postAction', this.link); - this.linkRequested = this.link; + this.isDisabled = true; + + axios.post(`${this.link}.json`) + .then(() => { + this.isDisabled = false; + this.$emit('pipelineActionRequestComplete'); + }) + .catch(() => { + this.isDisabled = false; + + createFlash(__('An error occurred while making the request.')); + }); }, }, }; @@ -80,6 +93,6 @@ btn-transparent ci-action-icon-container ci-action-icon-wrapper" data-container="body" :disabled="isDisabled" > - <icon :name="actionIcon" /> + <icon :name="actionIcon"/> </button> </template> diff --git a/app/assets/javascripts/pipelines/components/graph/dropdown_job_component.vue b/app/assets/javascripts/pipelines/components/graph/dropdown_job_component.vue index 4027d26098f..7bfe11ab8cd 100644 --- a/app/assets/javascripts/pipelines/components/graph/dropdown_job_component.vue +++ b/app/assets/javascripts/pipelines/components/graph/dropdown_job_component.vue @@ -42,11 +42,6 @@ export default { type: Object, required: true, }, - requestFinishedFor: { - type: String, - required: false, - default: '', - }, }, computed: { @@ -76,11 +71,15 @@ export default { e.stopPropagation(); }); }, + + pipelineActionRequestComplete() { + this.$emit('pipelineActionRequestComplete'); + }, }, }; </script> <template> - <div class="ci-job-dropdown-container"> + <div class="ci-job-dropdown-container dropdown"> <button v-tooltip type="button" @@ -110,7 +109,7 @@ export default { <job-component :job="item" css-class-job-name="mini-pipeline-graph-dropdown-item" - :request-finished-for="requestFinishedFor" + @pipelineActionRequestComplete="pipelineActionRequestComplete" /> </li> </ul> diff --git a/app/assets/javascripts/pipelines/components/graph/graph_component.vue b/app/assets/javascripts/pipelines/components/graph/graph_component.vue index 7b8a5edcbff..4ec67f6c01b 100644 --- a/app/assets/javascripts/pipelines/components/graph/graph_component.vue +++ b/app/assets/javascripts/pipelines/components/graph/graph_component.vue @@ -16,11 +16,6 @@ export default { type: Object, required: true, }, - requestFinishedFor: { - type: String, - required: false, - default: '', - }, }, computed: { @@ -51,6 +46,10 @@ export default { return className; }, + + refreshPipelineGraph() { + this.$emit('refreshPipelineGraph'); + }, }, }; </script> @@ -74,7 +73,7 @@ export default { :key="stage.name" :stage-connector-class="stageConnectorClass(index, stage)" :is-first-column="isFirstColumn(index)" - :request-finished-for="requestFinishedFor" + @refreshPipelineGraph="refreshPipelineGraph" /> </ul> </div> diff --git a/app/assets/javascripts/pipelines/components/graph/job_component.vue b/app/assets/javascripts/pipelines/components/graph/job_component.vue index c1f0f051b63..dc16d395bcb 100644 --- a/app/assets/javascripts/pipelines/components/graph/job_component.vue +++ b/app/assets/javascripts/pipelines/components/graph/job_component.vue @@ -46,11 +46,6 @@ export default { required: false, default: '', }, - requestFinishedFor: { - type: String, - required: false, - default: '', - }, }, computed: { status() { @@ -84,6 +79,11 @@ export default { return this.job.status && this.job.status.action && this.job.status.action.path; }, }, + methods: { + pipelineActionRequestComplete() { + this.$emit('pipelineActionRequestComplete'); + }, + }, }; </script> <template> @@ -96,6 +96,7 @@ export default { :class="cssClassJobName" data-container="body" data-html="true" + data-boundary="viewport" class="js-pipeline-graph-job-link" > @@ -126,7 +127,7 @@ export default { :tooltip-text="status.action.title" :link="status.action.path" :action-icon="status.action.icon" - :request-finished-for="requestFinishedFor" + @pipelineActionRequestComplete="pipelineActionRequestComplete" /> </div> </template> diff --git a/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue b/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue index 5461fdbbadd..f32368947e8 100644 --- a/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue +++ b/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue @@ -29,12 +29,6 @@ export default { required: false, default: '', }, - - requestFinishedFor: { - type: String, - required: false, - default: '', - }, }, methods: { @@ -49,6 +43,10 @@ export default { buildConnnectorClass(index) { return index === 0 && !this.isFirstColumn ? 'left-connector' : ''; }, + + pipelineActionRequestComplete() { + this.$emit('refreshPipelineGraph'); + }, }, }; </script> @@ -75,12 +73,13 @@ export default { v-if="job.size === 1" :job="job" css-class-job-name="build-content" + @pipelineActionRequestComplete="pipelineActionRequestComplete" /> <dropdown-job-component v-if="job.size > 1" :job="job" - :request-finished-for="requestFinishedFor" + @pipelineActionRequestComplete="pipelineActionRequestComplete" /> </li> diff --git a/app/assets/javascripts/pipelines/components/pipeline_url.vue b/app/assets/javascripts/pipelines/components/pipeline_url.vue index ceb4d9ca604..4d965733f95 100644 --- a/app/assets/javascripts/pipelines/components/pipeline_url.vue +++ b/app/assets/javascripts/pipelines/components/pipeline_url.vue @@ -46,7 +46,7 @@ }; </script> <template> - <div class="table-section section-15 hidden-xs hidden-sm pipeline-tags"> + <div class="table-section section-15 d-none d-sm-none d-md-block pipeline-tags"> <a :href="pipeline.path" class="js-pipeline-url-link"> @@ -69,35 +69,35 @@ <span v-if="pipeline.flags.latest" v-tooltip - class="js-pipeline-url-latest label label-success" + class="js-pipeline-url-latest badge badge-success" title="Latest pipeline for this branch"> latest </span> <span v-if="pipeline.flags.yaml_errors" v-tooltip - class="js-pipeline-url-yaml label label-danger" + class="js-pipeline-url-yaml badge badge-danger" :title="pipeline.yaml_errors"> yaml invalid </span> <span v-if="pipeline.flags.failure_reason" v-tooltip - class="js-pipeline-url-failure label label-danger" + class="js-pipeline-url-failure badge badge-danger" :title="pipeline.failure_reason"> error </span> <a v-if="pipeline.flags.auto_devops" tabindex="0" - class="js-pipeline-url-autodevops label label-info autodevops-badge" + class="js-pipeline-url-autodevops badge badge-info autodevops-badge" v-popover="popoverOptions" role="button"> Auto DevOps </a> <span v-if="pipeline.flags.stuck" - class="js-pipeline-url-stuck label label-warning"> + class="js-pipeline-url-stuck badge badge-warning"> stuck </span> </div> diff --git a/app/assets/javascripts/pipelines/components/pipelines_actions.vue b/app/assets/javascripts/pipelines/components/pipelines_actions.vue index 3297af7bde4..e9bc3cf14ca 100644 --- a/app/assets/javascripts/pipelines/components/pipelines_actions.vue +++ b/app/assets/javascripts/pipelines/components/pipelines_actions.vue @@ -63,7 +63,7 @@ <loading-icon v-if="isLoading" /> </button> - <ul class="dropdown-menu dropdown-menu-align-right"> + <ul class="dropdown-menu dropdown-menu-right"> <li v-for="(action, i) in actions" :key="i" diff --git a/app/assets/javascripts/pipelines/components/pipelines_artifacts.vue b/app/assets/javascripts/pipelines/components/pipelines_artifacts.vue index 1b9e0f917a4..31fcc9dd412 100644 --- a/app/assets/javascripts/pipelines/components/pipelines_artifacts.vue +++ b/app/assets/javascripts/pipelines/components/pipelines_artifacts.vue @@ -37,7 +37,7 @@ > </i> </button> - <ul class="dropdown-menu dropdown-menu-align-right"> + <ul class="dropdown-menu dropdown-menu-right"> <li v-for="(artifact, i) in artifacts" :key="i"> diff --git a/app/assets/javascripts/pipelines/components/pipelines_table.vue b/app/assets/javascripts/pipelines/components/pipelines_table.vue index 41986b827cd..4318abe97e0 100644 --- a/app/assets/javascripts/pipelines/components/pipelines_table.vue +++ b/app/assets/javascripts/pipelines/components/pipelines_table.vue @@ -37,6 +37,7 @@ return { pipelineId: '', endpoint: '', + cancelingPipeline: null, }; }, computed: { @@ -64,6 +65,7 @@ }, onSubmit() { eventHub.$emit('postAction', this.endpoint); + this.cancelingPipeline = this.pipelineId; }, }, }; @@ -106,6 +108,7 @@ :update-graph-dropdown="updateGraphDropdown" :auto-devops-help-path="autoDevopsHelpPath" :view-type="viewType" + :canceling-pipeline="cancelingPipeline" /> <modal diff --git a/app/assets/javascripts/pipelines/components/pipelines_table_row.vue b/app/assets/javascripts/pipelines/components/pipelines_table_row.vue index 498a97851fa..a3c17479e6f 100644 --- a/app/assets/javascripts/pipelines/components/pipelines_table_row.vue +++ b/app/assets/javascripts/pipelines/components/pipelines_table_row.vue @@ -9,6 +9,7 @@ import CommitComponent from '../../vue_shared/components/commit.vue'; import LoadingButton from '../../vue_shared/components/loading_button.vue'; import Icon from '../../vue_shared/components/icon.vue'; + import { PIPELINES_TABLE } from '../constants'; /** * Pipeline table row. @@ -45,11 +46,16 @@ type: String, required: true, }, + cancelingPipeline: { + type: String, + required: false, + default: null, + }, }, + pipelinesTable: PIPELINES_TABLE, data() { return { isRetrying: false, - isCancelling: false, }; }, computed: { @@ -225,12 +231,14 @@ isChildView() { return this.viewType === 'child'; }, + + isCancelling() { + return this.cancelingPipeline === this.pipeline.id; + }, }, methods: { handleCancelClick() { - this.isCancelling = true; - eventHub.$emit('openConfirmationModal', { pipelineId: this.pipeline.id, endpoint: this.pipeline.cancel_path, @@ -297,6 +305,7 @@ v-for="(stage, index) in pipeline.details.stages" :key="index"> <pipeline-stage + :type="$options.pipelinesTable" :stage="stage" :update-dropdown="updateGraphDropdown" /> @@ -322,7 +331,7 @@ <pipelines-artifacts-component v-if="pipeline.details.artifacts.length" - class="hidden-xs hidden-sm" + class="d-none d-sm-none d-md-block" :artifacts="pipeline.details.artifacts" /> diff --git a/app/assets/javascripts/pipelines/components/stage.vue b/app/assets/javascripts/pipelines/components/stage.vue index a65485c05eb..f9769815796 100644 --- a/app/assets/javascripts/pipelines/components/stage.vue +++ b/app/assets/javascripts/pipelines/components/stage.vue @@ -21,6 +21,7 @@ import Icon from '../../vue_shared/components/icon.vue'; import LoadingIcon from '../../vue_shared/components/loading_icon.vue'; import JobComponent from './graph/job_component.vue'; import tooltip from '../../vue_shared/directives/tooltip'; +import { PIPELINES_TABLE } from '../constants'; export default { components: { @@ -44,6 +45,12 @@ export default { required: false, default: false, }, + + type: { + type: String, + required: false, + default: '', + }, }, data() { @@ -133,6 +140,16 @@ export default { isDropdownOpen() { return this.$el.classList.contains('open'); }, + + pipelineActionRequestComplete() { + if (this.type === PIPELINES_TABLE) { + // warn the table to update + eventHub.$emit('refreshPipelinesTable'); + } else { + // close the dropdown in mr widget + $(this.$refs.dropdown).dropdown('toggle'); + } + }, }, }; </script> @@ -151,6 +168,7 @@ export default { id="stageDropdown" aria-haspopup="true" aria-expanded="false" + ref="dropdown" > <span @@ -188,6 +206,7 @@ export default { <job-component :job="job" css-class-job-name="mini-pipeline-graph-dropdown-item" + @pipelineActionRequestComplete="pipelineActionRequestComplete" /> </li> </ul> diff --git a/app/assets/javascripts/pipelines/components/time_ago.vue b/app/assets/javascripts/pipelines/components/time_ago.vue index cd54d26c9d3..79dbdca4010 100644 --- a/app/assets/javascripts/pipelines/components/time_ago.vue +++ b/app/assets/javascripts/pipelines/components/time_ago.vue @@ -75,7 +75,7 @@ </p> <p - class="finished-at hidden-xs hidden-sm" + class="finished-at d-none d-sm-none d-md-block" v-if="hasFinishedTime" > diff --git a/app/assets/javascripts/pipelines/constants.js b/app/assets/javascripts/pipelines/constants.js index b384c7500e7..eaa11a84cb9 100644 --- a/app/assets/javascripts/pipelines/constants.js +++ b/app/assets/javascripts/pipelines/constants.js @@ -1,2 +1,2 @@ -// eslint-disable-next-line import/prefer-default-export export const CANCEL_REQUEST = 'CANCEL_REQUEST'; +export const PIPELINES_TABLE = 'PIPELINES_TABLE'; diff --git a/app/assets/javascripts/pipelines/mixins/pipelines.js b/app/assets/javascripts/pipelines/mixins/pipelines.js index de0faf181e5..30b1eee186d 100644 --- a/app/assets/javascripts/pipelines/mixins/pipelines.js +++ b/app/assets/javascripts/pipelines/mixins/pipelines.js @@ -55,11 +55,13 @@ export default { eventHub.$on('postAction', this.postAction); eventHub.$on('retryPipeline', this.postAction); eventHub.$on('clickedDropdown', this.updateTable); + eventHub.$on('refreshPipelinesTable', this.fetchPipelines); }, beforeDestroy() { eventHub.$off('postAction', this.postAction); eventHub.$off('retryPipeline', this.postAction); eventHub.$off('clickedDropdown', this.updateTable); + eventHub.$off('refreshPipelinesTable', this.fetchPipelines); }, destroyed() { this.poll.stop(); diff --git a/app/assets/javascripts/pipelines/pipeline_details_bundle.js b/app/assets/javascripts/pipelines/pipeline_details_bundle.js index 04fe7958fe6..b49a16a87e6 100644 --- a/app/assets/javascripts/pipelines/pipeline_details_bundle.js +++ b/app/assets/javascripts/pipelines/pipeline_details_bundle.js @@ -25,30 +25,14 @@ export default () => { data() { return { mediator, - requestFinishedFor: null, }; }, - created() { - eventHub.$on('postAction', this.postAction); - }, - beforeDestroy() { - eventHub.$off('postAction', this.postAction); - }, methods: { - postAction(action) { - // Click was made, reset this variable - this.requestFinishedFor = null; - - this.mediator.service - .postAction(action) - .then(() => { - this.mediator.refreshPipeline(); - this.requestFinishedFor = action; - }) - .catch(() => { - this.requestFinishedFor = action; - Flash(__('An error occurred while making the request.')); - }); + requestRefreshPipelineGraph() { + // When an action is clicked + // (wether in the dropdown or in the main nodes, we refresh the big graph) + this.mediator.refreshPipeline() + .catch(() => Flash(__('An error occurred while making the request.'))); }, }, render(createElement) { @@ -56,7 +40,9 @@ export default () => { props: { isLoading: this.mediator.state.isLoading, pipeline: this.mediator.store.state.pipeline, - requestFinishedFor: this.requestFinishedFor, + }, + on: { + refreshPipelineGraph: this.requestRefreshPipelineGraph, }, }); }, diff --git a/app/assets/javascripts/profile/account/components/update_username.vue b/app/assets/javascripts/profile/account/components/update_username.vue index e5de3f69b01..a7a2a7235fd 100644 --- a/app/assets/javascripts/profile/account/components/update_username.vue +++ b/app/assets/javascripts/profile/account/components/update_username.vue @@ -86,7 +86,11 @@ Please update your Git repository remotes as soon as possible.`), <div class="form-group"> <label :for="$options.inputId">{{ s__('Profiles|Path') }}</label> <div class="input-group"> - <div class="input-group-addon">{{ rootUrl }}</div> + <div class="input-group-prepend"> + <div class="input-group-text"> + {{ rootUrl }} + </div> + </div> <input :id="$options.inputId" class="form-control" diff --git a/app/assets/javascripts/project_fork.js b/app/assets/javascripts/project_fork.js index 6fedd94a6a9..f5cd1c3cc3e 100644 --- a/app/assets/javascripts/project_fork.js +++ b/app/assets/javascripts/project_fork.js @@ -4,6 +4,6 @@ export default () => { $('.js-fork-thumbnail').on('click', function forkThumbnailClicked() { if ($(this).hasClass('disabled')) return false; - return $('.js-fork-content').toggle(); + return $('.js-fork-content').toggleClass('hidden'); }); }; diff --git a/app/assets/javascripts/project_label_subscription.js b/app/assets/javascripts/project_label_subscription.js index f31beb4dc78..6f06944ebb6 100644 --- a/app/assets/javascripts/project_label_subscription.js +++ b/app/assets/javascripts/project_label_subscription.js @@ -42,7 +42,7 @@ export default class ProjectLabelSubscription { const $button = $(button); if ($button.attr('data-original-title')) { - $button.tooltip('hide').attr('data-original-title', newAction).tooltip('fixTitle'); + $button.tooltip('hide').attr('data-original-title', newAction).tooltip('_fixTitle'); } return button; diff --git a/app/assets/javascripts/project_visibility.js b/app/assets/javascripts/project_visibility.js index 7c95c71e239..a52ac768e57 100644 --- a/app/assets/javascripts/project_visibility.js +++ b/app/assets/javascripts/project_visibility.js @@ -7,7 +7,7 @@ function setVisibilityOptions(namespaceSelector) { const selectedNamespace = namespaceSelector.options[namespaceSelector.selectedIndex]; const { name, visibility, visibilityLevel, showPath, editPath } = selectedNamespace.dataset; - document.querySelectorAll('.visibility-level-setting .radio').forEach((option) => { + document.querySelectorAll('.visibility-level-setting .form-check').forEach((option) => { const optionInput = option.querySelector('input[type=radio]'); const optionValue = optionInput ? optionInput.value : 0; const optionTitle = option.querySelector('.option-title'); diff --git a/app/assets/javascripts/projects/project_new.js b/app/assets/javascripts/projects/project_new.js index 93603dfc14d..888b1d6ce33 100644 --- a/app/assets/javascripts/projects/project_new.js +++ b/app/assets/javascripts/projects/project_new.js @@ -66,8 +66,8 @@ const bindEvents = () => { .on('click', (e) => { e.preventDefault(); }) .popover({ title: $pushNewProjectTipTrigger.data('title'), - placement: 'auto bottom', - html: 'true', + placement: 'bottom', + html: true, content: $('.push-new-project-tip-template').html(), }) .on('shown.bs.popover', () => { diff --git a/app/assets/javascripts/projects_dropdown/components/search.vue b/app/assets/javascripts/projects_dropdown/components/search.vue index 0c46ed184be..7fcd62dcdb8 100644 --- a/app/assets/javascripts/projects_dropdown/components/search.vue +++ b/app/assets/javascripts/projects_dropdown/components/search.vue @@ -46,7 +46,7 @@ <template> <div - class="search-input-container hidden-xs" + class="search-input-container d-none d-sm-block" > <input type="search" diff --git a/app/assets/javascripts/prometheus_metrics/prometheus_metrics.js b/app/assets/javascripts/prometheus_metrics/prometheus_metrics.js index 0a60f4845b2..1a75fdd75db 100644 --- a/app/assets/javascripts/prometheus_metrics/prometheus_metrics.js +++ b/app/assets/javascripts/prometheus_metrics/prometheus_metrics.js @@ -31,7 +31,7 @@ export default class PrometheusMetrics { /* eslint-disable class-methods-use-this */ handlePanelToggle(e) { const $toggleBtn = $(e.currentTarget); - const $currentPanelBody = $toggleBtn.closest('.panel').find('.panel-body'); + const $currentPanelBody = $toggleBtn.closest('.card').find('.card-body'); $currentPanelBody.toggleClass('hidden'); if ($toggleBtn.hasClass('fa-caret-down')) { $toggleBtn.removeClass('fa-caret-down').addClass('fa-caret-right'); diff --git a/app/assets/javascripts/registry/components/collapsible_container.vue b/app/assets/javascripts/registry/components/collapsible_container.vue index a03180e80e6..2fc3778820b 100644 --- a/app/assets/javascripts/registry/components/collapsible_container.vue +++ b/app/assets/javascripts/registry/components/collapsible_container.vue @@ -28,11 +28,6 @@ isOpen: false, }; }, - computed: { - clipboardText() { - return `docker pull ${this.repo.location}`; - }, - }, methods: { ...mapActions([ 'fetchRepos', @@ -84,12 +79,12 @@ <clipboard-button v-if="repo.location" - :text="clipboardText" + :text="repo.location" :title="repo.location" css-class="btn-default btn-transparent btn-clipboard" /> - <div class="controls hidden-xs pull-right"> + <div class="controls d-none d-sm-block float-right"> <button v-if="repo.canDelete" type="button" diff --git a/app/assets/javascripts/registry/components/table_registry.vue b/app/assets/javascripts/registry/components/table_registry.vue index a2227b2f554..e4a4b3bb129 100644 --- a/app/assets/javascripts/registry/components/table_registry.vue +++ b/app/assets/javascripts/registry/components/table_registry.vue @@ -56,10 +56,6 @@ .catch(() => this.showError(errorMessagesTypes.FETCH_REGISTRY)); }, - clipboardText(text) { - return `docker pull ${text}`; - }, - showError(message) { Flash(errorMessages[message]); }, @@ -89,7 +85,7 @@ <clipboard-button v-if="item.location" :title="item.location" - :text="clipboardText(item.location)" + :text="item.location" css-class="btn-default btn-transparent btn-clipboard" /> </td> @@ -124,7 +120,7 @@ <button v-if="item.canDelete" type="button" - class="js-delete-registry btn btn-danger hidden-xs pull-right" + class="js-delete-registry btn btn-danger d-none d-sm-block float-right" :title="s__('ContainerRegistry|Remove tag')" :aria-label="s__('ContainerRegistry|Remove tag')" data-container="body" diff --git a/app/assets/javascripts/right_sidebar.js b/app/assets/javascripts/right_sidebar.js index 6eb0b62fa1c..2afcf4626b8 100644 --- a/app/assets/javascripts/right_sidebar.js +++ b/app/assets/javascripts/right_sidebar.js @@ -108,7 +108,7 @@ Sidebar.prototype.todoUpdateDone = function(data) { .attr('title', $el.data(`${attrPrefix}Text`)); if ($el.hasClass('has-tooltip')) { - $el.tooltip('fixTitle'); + $el.tooltip('_fixTitle'); } if ($el.data(`${attrPrefix}Icon`)) { diff --git a/app/assets/javascripts/shortcuts_navigation.js b/app/assets/javascripts/shortcuts_navigation.js index a4d10850471..78f7353eb0d 100644 --- a/app/assets/javascripts/shortcuts_navigation.js +++ b/app/assets/javascripts/shortcuts_navigation.js @@ -7,7 +7,7 @@ export default class ShortcutsNavigation extends Shortcuts { super(); Mousetrap.bind('g p', () => findAndFollowLink('.shortcuts-project')); - Mousetrap.bind('g e', () => findAndFollowLink('.shortcuts-project-activity')); + Mousetrap.bind('g v', () => findAndFollowLink('.shortcuts-project-activity')); Mousetrap.bind('g f', () => findAndFollowLink('.shortcuts-tree')); Mousetrap.bind('g c', () => findAndFollowLink('.shortcuts-commits')); Mousetrap.bind('g j', () => findAndFollowLink('.shortcuts-builds')); @@ -16,9 +16,10 @@ export default class ShortcutsNavigation extends Shortcuts { Mousetrap.bind('g i', () => findAndFollowLink('.shortcuts-issues')); Mousetrap.bind('g b', () => findAndFollowLink('.shortcuts-issue-boards')); Mousetrap.bind('g m', () => findAndFollowLink('.shortcuts-merge_requests')); - Mousetrap.bind('g t', () => findAndFollowLink('.shortcuts-todos')); Mousetrap.bind('g w', () => findAndFollowLink('.shortcuts-wiki')); Mousetrap.bind('g s', () => findAndFollowLink('.shortcuts-snippets')); + Mousetrap.bind('g k', () => findAndFollowLink('.shortcuts-kubernetes')); + Mousetrap.bind('g e', () => findAndFollowLink('.shortcuts-environments')); Mousetrap.bind('i', () => findAndFollowLink('.shortcuts-new-issue')); this.enabledHelp.push('.hidden-shortcut.project'); diff --git a/app/assets/javascripts/sidebar/components/assignees/assignee_title.vue b/app/assets/javascripts/sidebar/components/assignees/assignee_title.vue index 5eeb2a41bae..284a258d3c9 100644 --- a/app/assets/javascripts/sidebar/components/assignees/assignee_title.vue +++ b/app/assets/javascripts/sidebar/components/assignees/assignee_title.vue @@ -41,7 +41,7 @@ export default { </i> <a v-if="editable" - class="js-sidebar-dropdown-toggle edit-link pull-right" + class="js-sidebar-dropdown-toggle edit-link float-right" href="#" > {{ __('Edit') }} @@ -49,7 +49,7 @@ export default { <a v-if="showToggle" aria-label="Toggle sidebar" - class="gutter-toggle pull-right js-sidebar-toggle" + class="gutter-toggle float-right js-sidebar-toggle" href="#" role="button" > diff --git a/app/assets/javascripts/sidebar/components/assignees/assignees.vue b/app/assets/javascripts/sidebar/components/assignees/assignees.vue index 2d00e8ac7e0..5a374d84796 100644 --- a/app/assets/javascripts/sidebar/components/assignees/assignees.vue +++ b/app/assets/javascripts/sidebar/components/assignees/assignees.vue @@ -130,6 +130,7 @@ export default { v-tooltip data-container="body" data-placement="left" + data-boundary="viewport" :title="collapsedTooltipTitle" > <i 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 7f0de722f61..3f6e2f05396 100644 --- a/app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue +++ b/app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue @@ -75,6 +75,7 @@ export default { v-tooltip data-container="body" data-placement="left" + data-boundary="viewport" :title="tooltipLabel" > <icon @@ -86,7 +87,7 @@ export default { {{ __('Confidentiality') }} <a v-if="isEditable" - class="pull-right confidential-edit" + class="float-right confidential-edit" href="#" @click.prevent="toggleForm" > diff --git a/app/assets/javascripts/sidebar/components/confidential/edit_form.vue b/app/assets/javascripts/sidebar/components/confidential/edit_form.vue index 3783f71a848..4165aa19acf 100644 --- a/app/assets/javascripts/sidebar/components/confidential/edit_form.vue +++ b/app/assets/javascripts/sidebar/components/confidential/edit_form.vue @@ -32,7 +32,7 @@ export default { </script> <template> - <div class="dropdown open"> + <div class="dropdown show"> <div class="dropdown-menu sidebar-item-warning-message"> <div> <p diff --git a/app/assets/javascripts/sidebar/components/lock/edit_form.vue b/app/assets/javascripts/sidebar/components/lock/edit_form.vue index e1e4715826a..d392977e5e2 100644 --- a/app/assets/javascripts/sidebar/components/lock/edit_form.vue +++ b/app/assets/javascripts/sidebar/components/lock/edit_form.vue @@ -41,7 +41,7 @@ export default { </script> <template> - <div class="dropdown open"> + <div class="dropdown show"> <div class="dropdown-menu sidebar-item-warning-message"> <p class="text" diff --git a/app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue b/app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue index 1a5e7b67eca..fb69c741dcd 100644 --- a/app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue +++ b/app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue @@ -99,6 +99,7 @@ export default { v-tooltip data-container="body" data-placement="left" + data-boundary="viewport" :title="tooltipLabel" > <icon @@ -112,7 +113,7 @@ export default { {{ sprintf(__('Lock %{issuableDisplayName}'), { issuableDisplayName: issuableDisplayName }) }} <button v-if="isEditable" - class="pull-right lock-edit" + class="float-right lock-edit" type="button" @click.prevent="toggleForm" > diff --git a/app/assets/javascripts/sidebar/components/participants/participants.vue b/app/assets/javascripts/sidebar/components/participants/participants.vue index 8f9e6761d20..0a945fc7fd5 100644 --- a/app/assets/javascripts/sidebar/components/participants/participants.vue +++ b/app/assets/javascripts/sidebar/components/participants/participants.vue @@ -84,6 +84,7 @@ v-tooltip data-container="body" data-placement="left" + data-boundary="viewport" :title="participantLabel" @click="onClickCollapsedIcon" > diff --git a/app/assets/javascripts/sidebar/components/subscriptions/subscriptions.vue b/app/assets/javascripts/sidebar/components/subscriptions/subscriptions.vue index f0df759ef7a..6745c1aafff 100644 --- a/app/assets/javascripts/sidebar/components/subscriptions/subscriptions.vue +++ b/app/assets/javascripts/sidebar/components/subscriptions/subscriptions.vue @@ -82,6 +82,7 @@ :title="notificationTooltip" data-container="body" data-placement="left" + data-boundary="viewport" > <icon :name="notificationIcon" @@ -91,12 +92,12 @@ /> </span> </div> - <span class="issuable-header-text hide-collapsed pull-left"> + <span class="issuable-header-text hide-collapsed float-left"> {{ __('Notifications') }} </span> <toggle-button ref="toggleButton" - class="pull-right hide-collapsed js-issuable-subscribe-button" + class="float-right hide-collapsed js-issuable-subscribe-button" :is-loading="showLoadingState" :value="subscribed" @change="toggleSubscription" diff --git a/app/assets/javascripts/sidebar/components/time_tracking/collapsed_state.vue b/app/assets/javascripts/sidebar/components/time_tracking/collapsed_state.vue index 9d9ee9dea4d..209af1ce152 100644 --- a/app/assets/javascripts/sidebar/components/time_tracking/collapsed_state.vue +++ b/app/assets/javascripts/sidebar/components/time_tracking/collapsed_state.vue @@ -114,6 +114,7 @@ v-tooltip data-container="body" data-placement="left" + data-boundary="viewport" :title="tooltipText" > <icon name="timer" /> diff --git a/app/assets/javascripts/sidebar/components/time_tracking/comparison_pane.vue b/app/assets/javascripts/sidebar/components/time_tracking/comparison_pane.vue index 82c4562f9a9..6f79310b1cc 100644 --- a/app/assets/javascripts/sidebar/components/time_tracking/comparison_pane.vue +++ b/app/assets/javascripts/sidebar/components/time_tracking/comparison_pane.vue @@ -71,7 +71,7 @@ export default { </div> </div> <div class="compare-display-container"> - <div class="compare-display pull-left"> + <div class="compare-display float-left"> <span class="compare-label"> {{ s__('TimeTracking|Spent') }} </span> @@ -79,7 +79,7 @@ export default { {{ timeSpentHumanReadable }} </span> </div> - <div class="compare-display estimated pull-right"> + <div class="compare-display estimated float-right"> <span class="compare-label"> {{ s__('TimeTrackingEstimated|Est') }} </span> diff --git a/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue b/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue index 8f5d0bee107..7d56d2fa5ee 100644 --- a/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue +++ b/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue @@ -116,7 +116,7 @@ export default { <div class="title hide-collapsed"> {{ __('Time tracking') }} <div - class="help-button pull-right" + class="help-button float-right" v-if="!showHelpState" @click="toggleHelpState(true)" > @@ -127,7 +127,7 @@ export default { </i> </div> <div - class="close-help-button pull-right" + class="close-help-button float-right" v-if="showHelpState" @click="toggleHelpState(false)" > diff --git a/app/assets/javascripts/users_select.js b/app/assets/javascripts/users_select.js index 8486019897d..cd954f75613 100644 --- a/app/assets/javascripts/users_select.js +++ b/app/assets/javascripts/users_select.js @@ -202,7 +202,7 @@ function UsersSelect(currentUser, els, options = {}) { tooltipTitle = __('Assignee'); } $value.html(assigneeTemplate(user)); - $collapsedSidebar.attr('title', tooltipTitle).tooltip('fixTitle'); + $collapsedSidebar.attr('title', tooltipTitle).tooltip('_fixTitle'); return $collapsedSidebar.html(collapsedAssigneeTemplate(user)); }); }; diff --git a/app/assets/javascripts/vue_merge_request_widget/components/deployment.vue b/app/assets/javascripts/vue_merge_request_widget/components/deployment.vue index 1fea231c816..1608858da22 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/deployment.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/deployment.vue @@ -127,7 +127,7 @@ export default { </span> <loading-button v-if="deployment.stop_url" - container-class="btn btn-default btn-xs prepend-left-default" + container-class="btn btn-default btn-sm prepend-left-default" label="Stop environment" :loading="isStopping" @click="stopEnvironment" diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author.vue index cb6e9858736..8338fde61c7 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author.vue @@ -2,7 +2,7 @@ import tooltip from '../../vue_shared/directives/tooltip'; export default { - name: 'MRWidgetAuthor', + name: 'MrWidgetAuthor', directives: { tooltip, }, diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author_time.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author_time.vue index 8f1fd809a81..644e4b7d81a 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author_time.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author_time.vue @@ -1,10 +1,10 @@ <script> - import mrWidgetAuthor from './mr_widget_author.vue'; + import MrWidgetAuthor from './mr_widget_author.vue'; export default { name: 'MRWidgetAuthorTime', components: { - mrWidgetAuthor, + MrWidgetAuthor, }, props: { actionText: { diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue index 18ee4c62bf1..51a0fda6555 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue @@ -131,7 +131,7 @@ export default { aria-hidden="true"> </i> </button> - <ul class="dropdown-menu dropdown-menu-align-right"> + <ul class="dropdown-menu dropdown-menu-right"> <li> <a class="js-download-email-patches" diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_maintainer_edit.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_maintainer_edit.vue deleted file mode 100644 index f0298f732ea..00000000000 --- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_maintainer_edit.vue +++ /dev/null @@ -1,20 +0,0 @@ -<script> - export default { - name: 'MRWidgetMaintainerEdit', - props: { - maintainerEditAllowed: { - type: Boolean, - default: false, - required: false, - }, - }, - }; -</script> - -<template> - <section class="mr-info-list mr-links"> - <p v-if="maintainerEditAllowed"> - {{ s__("mrWidget|Allows edits from maintainers") }} - </p> - </section> -</template> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.vue index ebaf2b972eb..b404a592234 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_failed.vue @@ -42,7 +42,7 @@ @click="refreshWidget" :disabled="isRefreshing" type="button" - class="btn btn-xs btn-default" + class="btn btn-sm btn-default" > <loading-icon v-if="isRefreshing" diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue index dad4b0fe49d..5c1500ab801 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue @@ -43,13 +43,13 @@ To merge this request, first rebase locally.`) }} <a v-if="mr.canMerge && mr.conflictResolutionPath" :href="mr.conflictResolutionPath" - class="js-resolve-conflicts-button btn btn-default btn-xs" + class="js-resolve-conflicts-button btn btn-default btn-sm" > {{ s__("mrWidget|Resolve conflicts") }} </a> <button v-if="mr.canMerge" - class="js-merge-locally-button btn btn-default btn-xs" + class="js-merge-locally-button btn btn-default btn-sm" data-toggle="modal" data-target="#modal_merge_info" > diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue index 7d366c495f0..05fecd4de35 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_failed_to_merge.vue @@ -98,7 +98,7 @@ export default { </span> <button @click="refresh" - class="btn btn-default btn-xs js-refresh-button" + class="btn btn-default btn-sm js-refresh-button" type="button" > {{ s__("mrWidget|Refresh now") }} diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds.vue index 7ff7fc7988a..e8352c362d6 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merge_when_pipeline_succeeds.vue @@ -1,13 +1,13 @@ <script> import Flash from '../../../flash'; import statusIcon from '../mr_widget_status_icon.vue'; - import mrWidgetAuthor from '../../components/mr_widget_author.vue'; + import MrWidgetAuthor from '../../components/mr_widget_author.vue'; import eventHub from '../../event_hub'; export default { name: 'MRWidgetMergeWhenPipelineSucceeds', components: { - mrWidgetAuthor, + MrWidgetAuthor, statusIcon, }, props: { @@ -94,7 +94,7 @@ :disabled="isCancellingAutoMerge" role="button" href="#" - class="btn btn-xs btn-default js-cancel-auto-merge"> + class="btn btn-sm btn-default js-cancel-auto-merge"> <i v-if="isCancellingAutoMerge" class="fa fa-spinner fa-spin" @@ -129,7 +129,7 @@ :disabled="isRemovingSourceBranch" @click.prevent="removeSourceBranch" role="button" - class="btn btn-xs btn-default js-remove-source-branch" + class="btn btn-sm btn-default js-remove-source-branch" href="#" > <i diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue index 3e36a3a10f9..8c7e0664559 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue @@ -118,7 +118,7 @@ <a v-if="mr.canRevertInCurrentMR" v-tooltip - class="btn btn-close btn-xs" + class="btn btn-close btn-sm" href="#modal-revert-commit" data-toggle="modal" data-container="body" @@ -129,7 +129,7 @@ <a v-else-if="mr.revertInForkPath" v-tooltip - class="btn btn-close btn-xs" + class="btn btn-close btn-sm" data-method="post" :href="mr.revertInForkPath" :title="revertTitle" @@ -139,7 +139,7 @@ <a v-if="mr.canCherryPickInCurrentMR" v-tooltip - class="btn btn-default btn-xs" + class="btn btn-default btn-sm" href="#modal-cherry-pick-commit" data-toggle="modal" data-container="body" @@ -150,7 +150,7 @@ <a v-else-if="mr.cherryPickInForkPath" v-tooltip - class="btn btn-default btn-xs" + class="btn btn-default btn-sm" data-method="post" :href="mr.cherryPickInForkPath" :title="cherryPickTitle" @@ -189,7 +189,7 @@ @click="removeSourceBranch" :disabled="isMakingRequest" type="button" - class="btn btn-xs btn-default js-remove-branch-button" + class="btn btn-sm btn-default js-remove-branch-button" > {{ s__("mrWidget|Remove Source Branch") }} </button> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_squash_before_merge.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_squash_before_merge.vue index bf8628d18a6..926a3172412 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_squash_before_merge.js +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_squash_before_merge.vue @@ -10,6 +10,6 @@ In EE, the configuration extends this object to add a functioning squash-before- button. */ -export default { - template: '', -}; +<script> + export default {}; +</script> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/nothing_to_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/nothing_to_merge.vue index 3d9161f6926..086dbabe77e 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/nothing_to_merge.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/nothing_to_merge.vue @@ -18,10 +18,10 @@ export default { <template> <div class="mr-widget-body mr-widget-empty-state"> <div class="row"> - <div class="artwork col-sm-5 col-sm-push-7 col-xs-12 text-center"> + <div class="artwork col-md-5 order-md-last col-12 text-center"> <span v-html="emptyStateSVG"></span> </div> - <div class="text col-sm-7 col-sm-pull-5 col-xs-12"> + <div class="text col-md-7 order-md-first col-12"> <span> Merge requests are a place to propose changes you have made to a project and discuss those changes with others. diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue index 0264625a526..1d1c8ebc179 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue @@ -312,7 +312,7 @@ export default { v-else @click="toggleCommitMessageEditor" :disabled="isMergeButtonDisabled" - class="js-modify-commit-message-button btn btn-default btn-xs" + class="js-modify-commit-message-button btn btn-default btn-sm" type="button"> Modify commit message </button> @@ -329,7 +329,7 @@ export default { class="prepend-top-default commit-message-editor"> <div class="form-group clearfix"> <label - class="control-label" + class="col-form-label" for="commit-message"> Commit message </label> diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/unresolved_discussions.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/unresolved_discussions.vue index a1f7e696795..8ea3f22ecc2 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/unresolved_discussions.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/unresolved_discussions.vue @@ -28,7 +28,7 @@ export default { <a v-if="mr.createIssueToResolveDiscussionsPath" :href="mr.createIssueToResolveDiscussionsPath" - class="btn btn-default btn-xs js-create-issue" + class="btn btn-default btn-sm js-create-issue" > {{ s__("mrWidget|Create an issue to resolve them later") }} </a> diff --git a/app/assets/javascripts/vue_merge_request_widget/dependencies.js b/app/assets/javascripts/vue_merge_request_widget/dependencies.js index 7f5f28091da..15097fa2a3f 100644 --- a/app/assets/javascripts/vue_merge_request_widget/dependencies.js +++ b/app/assets/javascripts/vue_merge_request_widget/dependencies.js @@ -15,7 +15,6 @@ export { default as WidgetHeader } from './components/mr_widget_header.vue'; export { default as WidgetMergeHelp } from './components/mr_widget_merge_help.vue'; export { default as WidgetPipeline } from './components/mr_widget_pipeline.vue'; export { default as Deployment } from './components/deployment.vue'; -export { default as WidgetMaintainerEdit } from './components/mr_widget_maintainer_edit.vue'; export { default as WidgetRelatedLinks } from './components/mr_widget_related_links.vue'; export { default as MergedState } from './components/states/mr_widget_merged.vue'; export { default as FailedToMerge } from './components/states/mr_widget_failed_to_merge.vue'; @@ -41,8 +40,8 @@ export { default as MRWidgetService } from './services/mr_widget_service'; export { default as eventHub } from './event_hub'; export { default as getStateKey } from './stores/get_state_key'; export { default as stateMaps } from './stores/state_maps'; -export { default as SquashBeforeMerge } from './components/states/mr_widget_squash_before_merge'; +export { default as SquashBeforeMerge } from './components/states/mr_widget_squash_before_merge.vue'; export { default as notify } from '../lib/utils/notify'; export { default as SourceBranchRemovalStatus } from './components/source_branch_removal_status.vue'; -export { default as mrWidgetOptions } from './mr_widget_options'; +export { default as mrWidgetOptions } from './mr_widget_options.vue'; diff --git a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.js b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue index 345f9ac1b4b..f69fe03fcb3 100644 --- a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.js +++ b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue @@ -1,12 +1,13 @@ +<script> + import Project from '~/pages/projects/project'; import SmartInterval from '~/smart_interval'; -import Flash from '../flash'; +import createFlash from '../flash'; import { WidgetHeader, WidgetMergeHelp, WidgetPipeline, Deployment, - WidgetMaintainerEdit, WidgetRelatedLinks, MergedState, ClosedState, @@ -40,10 +41,39 @@ import { setFavicon } from '../lib/utils/common_utils'; export default { el: '#js-vue-mr-widget', name: 'MRWidget', + components: { + 'mr-widget-header': WidgetHeader, + 'mr-widget-merge-help': WidgetMergeHelp, + 'mr-widget-pipeline': WidgetPipeline, + Deployment, + 'mr-widget-related-links': WidgetRelatedLinks, + 'mr-widget-merged': MergedState, + 'mr-widget-closed': ClosedState, + 'mr-widget-merging': MergingState, + 'mr-widget-failed-to-merge': FailedToMerge, + 'mr-widget-wip': WorkInProgressState, + 'mr-widget-archived': ArchivedState, + 'mr-widget-conflicts': ConflictsState, + 'mr-widget-nothing-to-merge': NothingToMergeState, + 'mr-widget-not-allowed': NotAllowedState, + 'mr-widget-missing-branch': MissingBranchState, + 'mr-widget-ready-to-merge': ReadyToMergeState, + 'sha-mismatch': ShaMismatchState, + 'mr-widget-squash-before-merge': SquashBeforeMerge, + 'mr-widget-checking': CheckingState, + 'mr-widget-unresolved-discussions': UnresolvedDiscussionsState, + 'mr-widget-pipeline-blocked': PipelineBlockedState, + 'mr-widget-pipeline-failed': PipelineFailedState, + 'mr-widget-merge-when-pipeline-succeeds': MergeWhenPipelineSucceedsState, + 'mr-widget-auto-merge-failed': AutoMergeFailed, + 'mr-widget-rebase': RebaseState, + SourceBranchRemovalStatus, + }, props: { mrData: { type: Object, required: false, + default: null, }, }, data() { @@ -72,6 +102,13 @@ export default { (!this.mr.isNothingToMergeState && !this.mr.isMergedState); }, }, + created() { + this.initPolling(); + this.bindEventHubListeners(); + }, + mounted() { + this.handleMounted(); + }, methods: { createService(store) { const endpoints = { @@ -99,7 +136,7 @@ export default { cb.call(null, data); } }) - .catch(() => new Flash('Something went wrong. Please try again.')); + .catch(() => createFlash('Something went wrong. Please try again.')); }, initPolling() { this.pollingInterval = new SmartInterval({ @@ -134,7 +171,7 @@ export default { } }) .catch(() => { - new Flash('Something went wrong while fetching the environments for this merge request. Please try again.'); // eslint-disable-line + createFlash('Something went wrong while fetching the environments for this merge request. Please try again.'); // eslint-disable-line }); }, fetchActionsContent() { @@ -147,7 +184,7 @@ export default { Project.initRefSwitcher(); } }) - .catch(() => new Flash('Something went wrong. Please try again.')); + .catch(() => createFlash('Something went wrong. Please try again.')); }, handleNotification(data) { if (data.ci_status === this.mr.ciStatus) return; @@ -202,76 +239,53 @@ export default { this.initDeploymentsPolling(); }, }, - created() { - this.initPolling(); - this.bindEventHubListeners(); - }, - mounted() { - this.handleMounted(); - }, - components: { - 'mr-widget-header': WidgetHeader, - 'mr-widget-merge-help': WidgetMergeHelp, - 'mr-widget-pipeline': WidgetPipeline, - Deployment, - 'mr-widget-maintainer-edit': WidgetMaintainerEdit, - 'mr-widget-related-links': WidgetRelatedLinks, - 'mr-widget-merged': MergedState, - 'mr-widget-closed': ClosedState, - 'mr-widget-merging': MergingState, - 'mr-widget-failed-to-merge': FailedToMerge, - 'mr-widget-wip': WorkInProgressState, - 'mr-widget-archived': ArchivedState, - 'mr-widget-conflicts': ConflictsState, - 'mr-widget-nothing-to-merge': NothingToMergeState, - 'mr-widget-not-allowed': NotAllowedState, - 'mr-widget-missing-branch': MissingBranchState, - 'mr-widget-ready-to-merge': ReadyToMergeState, - 'mr-widget-sha-mismatch': ShaMismatchState, - 'mr-widget-squash-before-merge': SquashBeforeMerge, - 'mr-widget-checking': CheckingState, - 'mr-widget-unresolved-discussions': UnresolvedDiscussionsState, - 'mr-widget-pipeline-blocked': PipelineBlockedState, - 'mr-widget-pipeline-failed': PipelineFailedState, - 'mr-widget-merge-when-pipeline-succeeds': MergeWhenPipelineSucceedsState, - 'mr-widget-auto-merge-failed': AutoMergeFailed, - 'mr-widget-rebase': RebaseState, - SourceBranchRemovalStatus, - }, - template: ` - <div class="mr-state-widget prepend-top-default"> - <mr-widget-header :mr="mr" /> - <mr-widget-pipeline - v-if="shouldRenderPipelines" - :pipeline="mr.pipeline" - :ci-status="mr.ciStatus" - :has-ci="mr.hasCI" - /> - <deployment - v-for="deployment in mr.deployments" - :key="deployment.id" - :deployment="deployment" +}; +</script> +<template> + <div class="mr-state-widget prepend-top-default"> + <mr-widget-header + :mr="mr" + /> + <mr-widget-pipeline + v-if="shouldRenderPipelines" + :pipeline="mr.pipeline" + :ci-status="mr.ciStatus" + :has-ci="mr.hasCI" + /> + <deployment + v-for="deployment in mr.deployments" + :key="deployment.id" + :deployment="deployment" + /> + <div class="mr-widget-section"> + <component + :is="componentName" + :mr="mr" + :service="service" + /> + + <section + v-if="mr.maintainerEditAllowed" + class="mr-info-list mr-links" + > + {{ s__("mrWidget|Allows edits from maintainers") }} + </section> + + <mr-widget-related-links + v-if="shouldRenderRelatedLinks" + :state="mr.state" + :related-links="mr.relatedLinks" + /> + + <source-branch-removal-status + v-if="shouldRenderSourceBranchRemovalStatus" /> - <div class="mr-widget-section"> - <component - :is="componentName" - :mr="mr" - :service="service" /> - <mr-widget-maintainer-edit - :maintainerEditAllowed="mr.maintainerEditAllowed" /> - <mr-widget-related-links - v-if="shouldRenderRelatedLinks" - :state="mr.state" - :related-links="mr.relatedLinks" /> - <source-branch-removal-status - v-if="shouldRenderSourceBranchRemovalStatus" - /> - </div> - <div - class="mr-widget-footer" - v-if="shouldRenderMergeHelp"> - <mr-widget-merge-help /> - </div> </div> - `, -}; + <div + class="mr-widget-footer" + v-if="shouldRenderMergeHelp" + > + <mr-widget-merge-help /> + </div> + </div> +</template> diff --git a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/download_viewer.vue b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/download_viewer.vue index 395a71acccf..7b5367ac19b 100644 --- a/app/assets/javascripts/vue_shared/components/content_viewer/viewers/download_viewer.vue +++ b/app/assets/javascripts/vue_shared/components/content_viewer/viewers/download_viewer.vue @@ -42,7 +42,7 @@ export default { target="_blank"> <icon name="download" - css-classes="pull-left append-right-8" + css-classes="float-left append-right-8" :size="16" /> {{ __('Download') }} diff --git a/app/assets/javascripts/vue_shared/components/deprecated_modal.vue b/app/assets/javascripts/vue_shared/components/deprecated_modal.vue index dcf1489b37c..424af5a0293 100644 --- a/app/assets/javascripts/vue_shared/components/deprecated_modal.vue +++ b/app/assets/javascripts/vue_shared/components/deprecated_modal.vue @@ -87,7 +87,7 @@ <div :id="id" class="modal" - :class="id ? '' : 'show'" + :class="id ? '' : 'd-block'" role="dialog" tabindex="-1" > @@ -99,12 +99,12 @@ <div class="modal-content"> <div class="modal-header"> <slot name="header"> - <h4 class="modal-title pull-left"> + <h4 class="modal-title float-left"> {{ title }} </h4> <button type="button" - class="close pull-right" + class="close float-right" @click="emitCancel($event)" data-dismiss="modal" aria-label="Close" @@ -166,7 +166,7 @@ </div> <div v-if="!id" - class="modal-backdrop fade in" + class="modal-backdrop fade show" > </div> </div> diff --git a/app/assets/javascripts/vue_shared/components/gl_modal.vue b/app/assets/javascripts/vue_shared/components/gl_modal.vue index f28e5e2715d..d5d5a7d3798 100644 --- a/app/assets/javascripts/vue_shared/components/gl_modal.vue +++ b/app/assets/javascripts/vue_shared/components/gl_modal.vue @@ -53,6 +53,11 @@ export default { <div class="modal-content"> <div class="modal-header"> <slot name="header"> + <h4 class="modal-title"> + <slot name="title"> + {{ headerTitleText }} + </slot> + </h4> <button type="button" class="close js-modal-close-action" @@ -62,11 +67,6 @@ export default { > <span aria-hidden="true">×</span> </button> - <h4 class="modal-title"> - <slot name="title"> - {{ headerTitleText }} - </slot> - </h4> </slot> </div> diff --git a/app/assets/javascripts/vue_shared/components/header_ci_component.vue b/app/assets/javascripts/vue_shared/components/header_ci_component.vue index 088187ed348..ca17fa06a00 100644 --- a/app/assets/javascripts/vue_shared/components/header_ci_component.vue +++ b/app/assets/javascripts/vue_shared/components/header_ci_component.vue @@ -163,8 +163,8 @@ export default { <button v-if="hasSidebarButton" type="button" - class="btn btn-default visible-xs-block -visible-sm-block sidebar-toggle-btn js-sidebar-build-toggle js-sidebar-build-toggle-header" + class="btn btn-default d-block d-sm-none d-md-none +sidebar-toggle-btn js-sidebar-build-toggle js-sidebar-build-toggle-header" aria-label="Toggle Sidebar" id="toggleSidebar" > diff --git a/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue b/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue index c0ee88bbf72..d63318f3da6 100644 --- a/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue +++ b/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue @@ -111,7 +111,7 @@ Attach a file </button> <button - class="btn btn-default btn-xs hide button-cancel-uploading-files" + class="btn btn-default btn-sm hide button-cancel-uploading-files" type="button" > Cancel diff --git a/app/assets/javascripts/vue_shared/components/navigation_tabs.vue b/app/assets/javascripts/vue_shared/components/navigation_tabs.vue index 92d187e24bf..08d4936f480 100644 --- a/app/assets/javascripts/vue_shared/components/navigation_tabs.vue +++ b/app/assets/javascripts/vue_shared/components/navigation_tabs.vue @@ -67,7 +67,7 @@ export default { <span v-if="shouldRenderBadge(tab.count)" - class="badge" + class="badge badge-pill" > {{ tab.count }} </span> diff --git a/app/assets/javascripts/vue_shared/components/notes/placeholder_note.vue b/app/assets/javascripts/vue_shared/components/notes/placeholder_note.vue index 50b1508691b..eccba61a8c0 100644 --- a/app/assets/javascripts/vue_shared/components/notes/placeholder_note.vue +++ b/app/assets/javascripts/vue_shared/components/notes/placeholder_note.vue @@ -54,7 +54,7 @@ <div class="note-header"> <div class="note-header-info"> <a :href="getUserData.path"> - <span class="hidden-xs">{{ getUserData.name }}</span> + <span class="d-none d-sm-block">{{ getUserData.name }}</span> <span class="note-headline-light">@{{ getUserData.username }}</span> </a> </div> diff --git a/app/assets/javascripts/vue_shared/components/sidebar/date_picker.vue b/app/assets/javascripts/vue_shared/components/sidebar/date_picker.vue index 3fcacd156c5..71ec34f2c7a 100644 --- a/app/assets/javascripts/vue_shared/components/sidebar/date_picker.vue +++ b/app/assets/javascripts/vue_shared/components/sidebar/date_picker.vue @@ -116,7 +116,7 @@ v-if="isLoading" :inline="true" /> - <div class="pull-right"> + <div class="float-right"> <button v-if="editable && !editing" type="button" diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_create_label.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_create_label.vue index 34a07f33a23..3c400afdc1d 100644 --- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_create_label.vue +++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_create_label.vue @@ -77,13 +77,13 @@ export default { <div class="clearfix"> <button type="button" - class="btn btn-primary pull-left js-new-label-btn disabled" + class="btn btn-primary float-left js-new-label-btn disabled" > {{ __('Create') }} </button> <button type="button" - class="btn btn-default pull-right js-cancel-label-btn" + class="btn btn-default float-right js-cancel-label-btn" > {{ __('Cancel') }} </button> diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_title.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_title.vue index 7da82e90e29..9ac32ff13c6 100644 --- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_title.vue +++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_title.vue @@ -21,7 +21,7 @@ export default { </i> <button type="button" - class="edit-link btn btn-blank pull-right js-sidebar-dropdown-toggle" + class="edit-link btn btn-blank float-right js-sidebar-dropdown-toggle" > {{ __('Edit') }} </button> diff --git a/app/assets/javascripts/vue_shared/components/time_ago_tooltip.vue b/app/assets/javascripts/vue_shared/components/time_ago_tooltip.vue index bec4e7c99b6..368eeb6c453 100644 --- a/app/assets/javascripts/vue_shared/components/time_ago_tooltip.vue +++ b/app/assets/javascripts/vue_shared/components/time_ago_tooltip.vue @@ -40,7 +40,7 @@ export default { :class="cssClass" :title="tooltipTitle(time)" :data-placement="tooltipPlacement" - data-container="body"> - {{ timeFormated(time) }} + data-container="body" + v-text="timeFormated(time)"> </time> </template> diff --git a/app/assets/javascripts/vue_shared/directives/popover.js b/app/assets/javascripts/vue_shared/directives/popover.js index eb35294906b..c913bc34c68 100644 --- a/app/assets/javascripts/vue_shared/directives/popover.js +++ b/app/assets/javascripts/vue_shared/directives/popover.js @@ -17,6 +17,6 @@ export default { }, unbind(el) { - $(el).popover('destroy'); + $(el).popover('dispose'); }, }; diff --git a/app/assets/javascripts/vue_shared/directives/tooltip.js b/app/assets/javascripts/vue_shared/directives/tooltip.js index b7f7e9fec15..155e6b6698a 100644 --- a/app/assets/javascripts/vue_shared/directives/tooltip.js +++ b/app/assets/javascripts/vue_shared/directives/tooltip.js @@ -6,10 +6,10 @@ export default { }, componentUpdated(el) { - $(el).tooltip('fixTitle'); + $(el).tooltip('_fixTitle'); }, unbind(el) { - $(el).tooltip('destroy'); + $(el).tooltip('dispose'); }, }; diff --git a/app/assets/stylesheets/bootstrap_migration.scss b/app/assets/stylesheets/bootstrap_migration.scss new file mode 100644 index 00000000000..3b7ee5c73e6 --- /dev/null +++ b/app/assets/stylesheets/bootstrap_migration.scss @@ -0,0 +1,149 @@ +/* + * Scss to help with bootstrap 3 to 4 migration + */ + +$text-color: $gl-text-color; + +$brand-primary: $gl-primary; +$brand-success: $gl-success; +$brand-info: $gl-info; +$brand-warning: $gl-warning; +$brand-danger: $gl-danger; + +$border-radius-base: 3px !default; + +$modal-body-bg: $white-light; +$input-border: $border-color; +$input-border-focus: $focus-border-color; + +$padding-base-vertical: $gl-vert-padding; +$padding-base-horizontal: $gl-padding; + +html { + // Override default font size used in bs4 + font-size: 14px; +} + +button, +html [type="button"], +[type="reset"], +[type="submit"] { + // Override bootstrap reboot + -webkit-appearance: inherit; +} + +[role="button"] { + cursor: pointer; +} + +a { + color: $gl-link-color; +} + +.form-group.row .col-form-label { + // Bootstrap 4 aligns labels to the left + // for horizontal forms + @include media-breakpoint-up(md) { + text-align: right; + } +} + +table { + // Remove any table border lines + border-spacing: 0; +} + +.tooltip { + // Fix bootstrap4 bug whereby tooltips flicker when they are hovered over their borders + pointer-events: none; +} + +.popover { + font-size: 14px; +} + +@each $breakpoint in map-keys($grid-breakpoints) { + @include media-breakpoint-up($breakpoint) { + $infix: breakpoint-infix($breakpoint, $grid-breakpoints); + + .d#{$infix}-table-header-group { display: table-header-group !important; } + } +} + +.text-secondary { + // Override Bootstrap's light secondary color + // We have to use !important because bootstrap has that set as well + color: $gl-text-color-secondary !important; +} + +// Polyfill deprecated selectors + +.hidden { + display: none !important; + visibility: hidden !important; +} + +.hide { + display: none; +} + +.dropdown-toggle::after { + // Remove bootstrap's dropdown caret + display: none; +} + +.badge { + padding: 4px 5px; + font-size: 12px; + font-style: normal; + font-weight: $gl-font-weight-normal; + display: inline-block; + + &.badge-gray { + background-color: $label-gray-bg; + color: $gl-text-color; + text-shadow: none; + } + + &.badge-inverse { + background-color: $label-inverse-bg; + } +} + +.divider { + @extend .dropdown-divider; +} + +.info-well { + background: $theme-gray-50; + color: $gl-text-color; + border: 1px solid $border-color; + border-radius: 4px; + margin-bottom: 16px; + + .well-segment { + padding: 16px; + + &:not(:last-of-type) { + border-bottom: 1px solid $well-inner-border; + } + } +} + +.card { + &.card-without-border { + @extend .border-0; + } + + &.card-without-margin { + margin: 0; + } + + &.bg-light { + @extend .border-0; + } +} + +.nav-tabs .nav-link { + border: 0; +} diff --git a/app/assets/stylesheets/framework.scss b/app/assets/stylesheets/framework.scss index 9bd35183d8a..7c28024001f 100644 --- a/app/assets/stylesheets/framework.scss +++ b/app/assets/stylesheets/framework.scss @@ -1,7 +1,7 @@ @import 'framework/variables'; @import 'framework/mixins'; -@import 'framework/tw_bootstrap_variables'; -@import 'framework/tw_bootstrap'; +@import '../../../node_modules/bootstrap/scss/bootstrap'; +@import 'bootstrap_migration'; @import 'framework/layout'; @import 'framework/animations'; diff --git a/app/assets/stylesheets/framework/avatar.scss b/app/assets/stylesheets/framework/avatar.scss index 077d0424093..c1ec11e434a 100644 --- a/app/assets/stylesheets/framework/avatar.scss +++ b/app/assets/stylesheets/framework/avatar.scss @@ -31,7 +31,7 @@ .avatar { @extend .avatar-circle; - @include transition-property(none); + transition-property: none; width: 40px; height: 40px; diff --git a/app/assets/stylesheets/framework/badges.scss b/app/assets/stylesheets/framework/badges.scss index 6bbe32df772..57df9b969c3 100644 --- a/app/assets/stylesheets/framework/badges.scss +++ b/app/assets/stylesheets/framework/badges.scss @@ -1,4 +1,4 @@ -.badge { +.badge.badge-pill { font-weight: $gl-font-weight-normal; background-color: $badge-bg; color: $badge-color; diff --git a/app/assets/stylesheets/framework/banner.scss b/app/assets/stylesheets/framework/banner.scss index 02f3896d591..71bbab2065d 100644 --- a/app/assets/stylesheets/framework/banner.scss +++ b/app/assets/stylesheets/framework/banner.scss @@ -23,7 +23,7 @@ border-bottom: 1px solid $border-color; } - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { justify-content: center; flex-direction: column; align-items: center; diff --git a/app/assets/stylesheets/framework/blank.scss b/app/assets/stylesheets/framework/blank.scss index 9982a5779af..91dbb2a6365 100644 --- a/app/assets/stylesheets/framework/blank.scss +++ b/app/assets/stylesheets/framework/blank.scss @@ -37,7 +37,7 @@ flex: 0 0 100%; margin-bottom: 15px; - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { flex: 0 0 49%; &:nth-child(odd) { @@ -67,7 +67,7 @@ border: 1px solid $border-color; border-radius: $border-radius-default; - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { display: flex; align-items: center; padding: 50px 30px; @@ -89,12 +89,12 @@ } .blank-state-body { - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { text-align: center; margin-top: 20px; } - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { padding-left: 20px; } } diff --git a/app/assets/stylesheets/framework/blocks.scss b/app/assets/stylesheets/framework/blocks.scss index c60f65e7a85..c5be27f2d29 100644 --- a/app/assets/stylesheets/framework/blocks.scss +++ b/app/assets/stylesheets/framework/blocks.scss @@ -151,7 +151,7 @@ display: inline-block; margin-left: 5px; font-size: 18px; - color: $gray; + color: color("gray"); } p { @@ -195,7 +195,7 @@ } } - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { text-align: center; .avatar { @@ -315,7 +315,7 @@ } } - @media (max-width: $screen-sm-min) { + @include media-breakpoint-down(sm) { flex-direction: column; .inner-content { @@ -342,7 +342,7 @@ .btn { margin: $btn-side-margin 5px; - @media(max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { width: 100%; } } diff --git a/app/assets/stylesheets/framework/broadcast_messages.scss b/app/assets/stylesheets/framework/broadcast_messages.scss index 9b54fb94cdc..d3e7d751e63 100644 --- a/app/assets/stylesheets/framework/broadcast_messages.scss +++ b/app/assets/stylesheets/framework/broadcast_messages.scss @@ -19,3 +19,9 @@ @extend .broadcast-message; margin-bottom: 20px; } + +.toggle-colors { + input { + min-height: 34px; + } +} diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss index cd9d60b96d3..0115f542c88 100644 --- a/app/assets/stylesheets/framework/buttons.scss +++ b/app/assets/stylesheets/framework/buttons.scss @@ -304,7 +304,8 @@ padding: 0 5px; } -.input-group-btn { +.input-group-prepend, +.input-group-append { .btn { @include btn-middle; @@ -393,7 +394,7 @@ } } -@media (max-width: $screen-xs-max) { +@include media-breakpoint-down(xs) { .btn-wide-on-xs { width: 100%; } diff --git a/app/assets/stylesheets/framework/calendar.scss b/app/assets/stylesheets/framework/calendar.scss index c165ec0b94b..0b9dff64b0b 100644 --- a/app/assets/stylesheets/framework/calendar.scss +++ b/app/assets/stylesheets/framework/calendar.scss @@ -4,7 +4,7 @@ border-top: 0; direction: rtl; - @media (min-width: $screen-sm-min) and (max-width: $screen-md-max) { + @media (min-width: map-get($grid-breakpoints, sm)) and (max-width: map-get($grid-breakpoints, sm)) { overflow-x: auto; } } diff --git a/app/assets/stylesheets/framework/ci_variable_list.scss b/app/assets/stylesheets/framework/ci_variable_list.scss index 5fe835dd8f9..7207e5119ce 100644 --- a/app/assets/stylesheets/framework/ci_variable_list.scss +++ b/app/assets/stylesheets/framework/ci_variable_list.scss @@ -10,14 +10,14 @@ display: flex; align-items: flex-start; - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { align-items: flex-end; } &:not(:last-child) { margin-bottom: $gl-btn-padding; - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { margin-bottom: 3 * $gl-btn-padding; } } @@ -26,7 +26,7 @@ .ci-variable-body-item:last-child { margin-right: $ci-variable-remove-button-width; - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { margin-right: 0; } } @@ -35,7 +35,7 @@ display: none; } - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { .ci-variable-row-body { margin-right: $ci-variable-remove-button-width; } @@ -48,7 +48,7 @@ align-items: flex-start; width: 100%; - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { display: block; } } @@ -59,7 +59,7 @@ &:not(:last-child) { margin-right: $gl-btn-padding; - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { margin-right: 0; margin-bottom: $gl-btn-padding; } diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss index 2faea55a5f5..1e7b9534275 100644 --- a/app/assets/stylesheets/framework/common.scss +++ b/app/assets/stylesheets/framework/common.scss @@ -70,7 +70,7 @@ pre { padding: 0; } - &.well-pre { + &.card.card-body-pre { border: 1px solid $well-pre-bg; background: $gray-light; border-radius: 0; @@ -218,7 +218,7 @@ li.note { } .git_error_tips { - @extend .col-md-6; + @extend .col-lg-6; text-align: left; margin-top: 40px; @@ -308,7 +308,7 @@ img.emoji { .btn-sign-in { text-shadow: none; - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { margin-top: 8px; } } @@ -327,7 +327,7 @@ img.emoji { } } -.well { +.card.card-body { margin-bottom: $gl-padding; hr { @@ -336,7 +336,7 @@ img.emoji { } .search_box { - @extend .well; + @extend .card.card-body; text-align: center; } diff --git a/app/assets/stylesheets/framework/contextual_sidebar.scss b/app/assets/stylesheets/framework/contextual_sidebar.scss index e2d97d0298f..1a415e1b852 100644 --- a/app/assets/stylesheets/framework/contextual_sidebar.scss +++ b/app/assets/stylesheets/framework/contextual_sidebar.scss @@ -1,11 +1,11 @@ .page-with-contextual-sidebar { transition: padding-left $sidebar-transition-duration; - @media (min-width: $screen-md-min) { + @include media-breakpoint-up(md) { padding-left: $contextual-sidebar-collapsed-width; } - @media (min-width: $screen-lg-min) { + @include media-breakpoint-up(lg) { padding-left: $contextual-sidebar-width; } @@ -16,7 +16,7 @@ } .page-with-icon-sidebar { - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { padding-left: $contextual-sidebar-collapsed-width; } } @@ -75,7 +75,7 @@ transform: translate3d(0, 0, 0); &:not(.sidebar-collapsed-desktop) { - @media (min-width: $screen-sm-min) and (max-width: $screen-md-max) { + @media (min-width: map-get($grid-breakpoints, sm)) and (max-width: map-get($grid-breakpoints, sm)) { box-shadow: inset -2px 0 0 $border-color, 2px 1px 3px $dropdown-shadow-color; } @@ -88,7 +88,7 @@ overflow-x: hidden; } - .badge:not(.fly-out-badge), + .badge.badge-pill:not(.fly-out-badge), .sidebar-context-title, .nav-item-name { display: none; @@ -142,7 +142,7 @@ } } - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { left: (-$contextual-sidebar-width); } @@ -166,7 +166,7 @@ width: 100%; overflow: auto; - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { overflow: hidden; } } @@ -207,7 +207,7 @@ > li { > a { - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { margin-right: 2px; } @@ -222,7 +222,7 @@ } .sidebar-sub-level-items { - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { position: fixed; top: 0; left: 0; @@ -277,7 +277,7 @@ } } - .badge { + .badge.badge-pill { background-color: $inactive-badge-background; color: $gl-text-color-secondary; } @@ -291,7 +291,7 @@ padding-left: 11px; } - .badge { + .badge.badge-pill { font-weight: $gl-font-weight-bold; } @@ -339,7 +339,7 @@ } .toggle-sidebar-button { - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { display: none; } } @@ -420,7 +420,7 @@ color: $gl-text-color-secondary; } - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { display: flex; align-items: center; @@ -429,7 +429,7 @@ } } - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { + .breadcrumbs-links { padding-left: $gl-padding; border-left: 1px solid $gl-text-color-quaternary; @@ -437,7 +437,7 @@ } } -@media (max-width: $screen-xs-max) { +@include media-breakpoint-down(xs) { .close-nav-button { display: flex; } diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss index 6576f7ca3b3..b91d579cae6 100644 --- a/app/assets/stylesheets/framework/dropdowns.scss +++ b/app/assets/stylesheets/framework/dropdowns.scss @@ -24,7 +24,7 @@ display: none; } -.open { +.show.dropdown { .dropdown-menu, .dropdown-menu-nav { @include set-visible; @@ -32,7 +32,7 @@ max-height: $dropdown-max-height; overflow-y: auto; - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { width: 100%; } } @@ -188,7 +188,7 @@ text-decoration: none; - .badge { + .badge.badge-pill { background-color: darken($dropdown-link-hover-bg, 5%); } } @@ -214,11 +214,10 @@ .dropdown-menu, .dropdown-menu-nav { - @include set-invisible; + display: none; position: absolute; width: auto; top: 100%; - left: 0; z-index: 300; min-width: 240px; max-width: 500px; @@ -332,7 +331,7 @@ color: $gl-text-color-secondary; } - .badge + span:not(.badge) { + .badge.badge-pill + span:not(.badge.badge-pill) { // Expects up to 3 digits on the badge margin-right: 40px; } @@ -396,7 +395,7 @@ transform: translateY(0); } -.comment-type-dropdown.open .dropdown-menu { +.comment-type-dropdown.show .dropdown-menu { display: block; } @@ -477,16 +476,11 @@ .dropdown-select { width: $dropdown-width; - @media (max-width: $screen-sm-min) { + @include media-breakpoint-down(sm) { width: 100%; } } -.dropdown-menu-align-right { - left: auto; - right: 0; -} - .dropdown-menu-selectable { li { a, @@ -787,7 +781,7 @@ } } -@media (max-width: $screen-xs-max) { +@include media-breakpoint-down(xs) { .navbar-gitlab { li.header-projects, li.header-more, @@ -842,7 +836,7 @@ header.header-content .dropdown-menu.projects-dropdown-menu { width: 70%; } - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { flex-direction: column; width: 100%; height: auto; @@ -898,7 +892,7 @@ header.header-content .dropdown-menu.projects-dropdown-menu { height: 284px; } - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { .projects-list-frequent-container { width: auto; height: auto; @@ -939,7 +933,7 @@ header.header-content .dropdown-menu.projects-dropdown-menu { color: $gl-text-color-secondary; } - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { .project-item-metadata-container { float: none; } diff --git a/app/assets/stylesheets/framework/feature_highlight.scss b/app/assets/stylesheets/framework/feature_highlight.scss index 4f26cd015e4..cad915bc86f 100644 --- a/app/assets/stylesheets/framework/feature_highlight.scss +++ b/app/assets/stylesheets/framework/feature_highlight.scss @@ -79,7 +79,7 @@ border-right-color: $dropdown-border-color; } - .popover-content { + .popover-body { padding: 0; } } diff --git a/app/assets/stylesheets/framework/files.scss b/app/assets/stylesheets/framework/files.scss index d835d49d8b2..f77ec4b6a2c 100644 --- a/app/assets/stylesheets/framework/files.scss +++ b/app/assets/stylesheets/framework/files.scss @@ -75,7 +75,7 @@ padding: 8px $gl-padding; border-bottom: 1px solid $border-color; - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { text-align: left; } @@ -125,7 +125,7 @@ &.wiki { padding: $gl-padding; - @media (min-width: $screen-md-min) { + @include media-breakpoint-up(md) { padding: $gl-padding * 2; } } @@ -364,7 +364,7 @@ span.idiff { } } - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { display: block; .file-actions { diff --git a/app/assets/stylesheets/framework/filters.scss b/app/assets/stylesheets/framework/filters.scss index 621a4adc0cb..0ee5748952a 100644 --- a/app/assets/stylesheets/framework/filters.scss +++ b/app/assets/stylesheets/framework/filters.scss @@ -9,19 +9,19 @@ float: right; margin-right: 0; - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { float: none; } } } .filters-section { - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { display: inline-block; } } -@media (min-width: $screen-sm-min) { +@include media-breakpoint-up(sm) { .filter-item:not(:last-child) { margin-right: 6px; } @@ -37,7 +37,7 @@ } } -@media (max-width: $screen-xs-max) { +@include media-breakpoint-down(xs) { .filter-item { display: block; margin: 0 0 10px; @@ -53,7 +53,7 @@ display: -webkit-flex; display: flex; - @media (max-width: $screen-xs-min) { + @include media-breakpoint-down(xs) { -webkit-flex-direction: column; flex-direction: column; } @@ -193,7 +193,7 @@ border: 1px solid $border-color; background-color: $white-light; - @media (max-width: $screen-xs-min) { + @include media-breakpoint-down(xs) { -webkit-flex: 1 1 auto; flex: 1 1 auto; margin-bottom: 10px; @@ -264,7 +264,7 @@ max-width: 280px; overflow: auto; - @media (max-width: $screen-xs-min) { + @include media-breakpoint-down(xs) { width: auto; left: 0; right: 0; @@ -315,7 +315,7 @@ .filtered-search-history-dropdown { width: 40%; - @media (max-width: $screen-xs-min) { + @include media-breakpoint-down(xs) { left: 0; right: 0; max-width: none; @@ -353,7 +353,7 @@ } } -@media (max-width: $screen-xs-max) { +@include media-breakpoint-down(xs) { .issues-details-filters { padding: 0 0 10px; background-color: $white-light; @@ -361,7 +361,7 @@ } } -@media (max-width: $screen-xs) { +@include media-breakpoint-down(sm) { .filter-dropdown-container { .dropdown-toggle, .dropdown, diff --git a/app/assets/stylesheets/framework/flash.scss b/app/assets/stylesheets/framework/flash.scss index cb2f71b0033..52c3f18a682 100644 --- a/app/assets/stylesheets/framework/flash.scss +++ b/app/assets/stylesheets/framework/flash.scss @@ -8,19 +8,19 @@ .flash-notice { @extend .alert; - @extend .alert-info; + background-color: $blue-500; margin: 0; } .flash-warning { @extend .alert; - @extend .alert-warning; + background-color: $orange-500; margin: 0; } .flash-alert { @extend .alert; - @extend .alert-danger; + background-color: $red-500; margin: 0; .flash-text, @@ -42,14 +42,16 @@ .flash-success { @extend .alert; - @extend .alert-success; + background-color: $green-500; margin: 0; } .flash-notice, .flash-alert, - .flash-success { + .flash-success, + .flash-warning { border-radius: $border-radius-default; + color: $white-light; .container-fluid, .container-fluid.container-limited { @@ -72,7 +74,7 @@ } } -@media (max-width: $screen-sm-max) { +@include media-breakpoint-down(sm) { ul.notes { .flash-container.timeline-content { margin-left: 0; diff --git a/app/assets/stylesheets/framework/forms.scss b/app/assets/stylesheets/framework/forms.scss index 2c30311b1c1..c76ea532912 100644 --- a/app/assets/stylesheets/framework/forms.scss +++ b/app/assets/stylesheets/framework/forms.scss @@ -36,8 +36,8 @@ label { } } -.control-label { - @extend .col-sm-2; +.form-control-label { + @extend .col-md-2; } .inline-input-group { @@ -48,21 +48,21 @@ label { width: 150px; } -@media (min-width: $screen-sm-min) { +@include media-breakpoint-up(sm) { .custom-form-control { width: 150px; } } /* Medium devices (desktops, 992px and up) */ -@media (min-width: $screen-md-min) { +@include media-breakpoint-up(md) { .custom-form-control { width: 170px; } } /* Large devices (large desktops, 1200px and up) */ -@media (min-width: $screen-lg-min) { +@include media-breakpoint-up(lg) { .custom-form-control { width: 200px; } @@ -72,7 +72,7 @@ label { margin-left: 0; margin-right: 0; - .control-label { + .form-control-label { font-weight: $gl-font-weight-bold; padding-top: 4px; } @@ -83,7 +83,8 @@ label { font-family: $monospace_font; } - .input-group-btn .btn { + .input-group-prepend .btn, + .input-group-append .btn { padding: 3px $gl-btn-padding; background-color: $gray-light; border: 1px solid $border-color; @@ -102,10 +103,10 @@ label { } } - @media(max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { padding: 0 $gl-padding; - .control-label, + .form-control-label, .text-block { padding-left: 0; } @@ -120,6 +121,14 @@ label { @include box-shadow(none); border-radius: 2px; padding: $gl-vert-padding $gl-input-padding; + + &.input-short { + width: $input-short-width; + + @include media-breakpoint-up(md) { + width: $input-short-md-width; + } + } } .select-wrapper { @@ -155,8 +164,8 @@ label { margin-top: 35px; } -.form-group .control-label, -.form-group .control-label-full-width { +.form-group .form-control-label, +.form-group .form-control-label-full-width { font-weight: $gl-font-weight-normal; } @@ -170,17 +179,19 @@ label { max-width: 180px; } - .input-group-addon { + .input-group-prepend, + .input-group-append { background-color: $input-group-addon-bg; } - .input-group-addon:not(:first-child):not(:last-child) { + .input-group-prepend:not(:first-child):not(:last-child), + .input-group-append:not(:first-child):not(:last-child) { border-left: 0; border-right: 0; } } -.help-block { +.form-text.text-muted { margin-bottom: 0; margin-top: #{$grid-size / 2}; } @@ -221,7 +232,7 @@ label { } } -@media(max-width: $screen-xs-max) { +@include media-breakpoint-down(xs) { .remember-me { .remember-me-checkbox { margin-top: 0; diff --git a/app/assets/stylesheets/framework/gitlab_theme.scss b/app/assets/stylesheets/framework/gitlab_theme.scss index 0bbd6eb27c1..d6ae8cbb416 100644 --- a/app/assets/stylesheets/framework/gitlab_theme.scss +++ b/app/assets/stylesheets/framework/gitlab_theme.scss @@ -21,7 +21,7 @@ } .container-fluid { - .navbar-toggle { + .navbar-toggler { border-left: 1px solid lighten($color-700, 10%); } } @@ -63,7 +63,7 @@ &:hover, &:focus { - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { background-color: rgba($color-200, 0.2); } @@ -165,14 +165,14 @@ } } - .sidebar-top-level-items > li.active .badge { + .sidebar-top-level-items > li.active .badge.badge-pill { color: $color-800; } - .nav-links li.active a { - border-bottom-color: $color-500; + .nav-links li a.active { + border-bottom: 2px solid $color-500; - .badge { + .badge.badge-pill { font-weight: $gl-font-weight-bold; } } @@ -277,8 +277,8 @@ body { } .container-fluid { - .navbar-toggle, - .navbar-toggle:hover { + .navbar-toggler, + .navbar-toggler:hover { color: $theme-gray-700; border-left: 1px solid $theme-gray-200; } @@ -328,7 +328,7 @@ body { } } - .sidebar-top-level-items > li.active .badge { + .sidebar-top-level-items > li.active .badge.badge-pill { color: $theme-gray-900; } } diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss index 0136af76a13..2085e5646ef 100644 --- a/app/assets/stylesheets/framework/header.scss +++ b/app/assets/stylesheets/framework/header.scss @@ -37,6 +37,7 @@ } .header-content { + width: 100%; display: -webkit-flex; display: flex; justify-content: space-between; @@ -91,7 +92,7 @@ border-radius: $border-radius-default; .tanuki-logo { - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { margin-right: 8px; } } @@ -110,7 +111,7 @@ } &.menu-expanded { - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { .title-container { display: none; } @@ -133,13 +134,13 @@ border-top: 0; padding: 0; - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { flex: 1 1 auto; } .nav { - > li:not(.hidden-xs) a { - @media (max-width: $screen-xs-max) { + > li:not(.d-none) a { + @include media-breakpoint-down(xs) { margin-left: 0; min-width: 100%; } @@ -156,7 +157,7 @@ } } - .navbar-toggle { + .navbar-toggler { right: -10px; border-radius: 0; min-width: 45px; @@ -181,14 +182,14 @@ } .navbar-nav { - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { display: -webkit-flex; display: flex; padding-right: 10px; } li { - .badge { + .badge.badge-pill { box-shadow: none; font-weight: $gl-font-weight-bold; } @@ -197,7 +198,7 @@ .nav > li { &.header-user { - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { padding-left: 10px; } } @@ -208,7 +209,7 @@ padding: 6px 8px; height: 32px; - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { padding: 0; } @@ -324,8 +325,8 @@ fill: currentColor; } -.header-user .dropdown-menu-nav, -.header-new .dropdown-menu-nav { +.header-user .dropdown-menu, +.header-new .dropdown-menu { margin-top: $dropdown-vertical-offset; } @@ -378,7 +379,7 @@ margin-bottom: 0; line-height: 16px; - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { flex-wrap: wrap; } @@ -410,7 +411,7 @@ .breadcrumb-item-text { text-decoration: inherit; - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { @include str-truncated(128px); } } @@ -452,7 +453,7 @@ .navbar-nav { li { - .badge { + .badge.badge-pill { position: inherit; font-weight: $gl-font-weight-normal; margin-left: -6px; @@ -478,7 +479,7 @@ } } -@media (max-width: $screen-xs-max) { +@include media-breakpoint-down(xs) { .navbar-gitlab .container-fluid { font-size: 18px; @@ -493,7 +494,7 @@ margin-left: -8px; margin-right: -10px; - .nav > li:not(.hidden-xs) { + .nav > li:not(.d-none) { display: table-cell !important; width: 25%; @@ -514,7 +515,7 @@ } .header-user { - .dropdown-menu-nav { + .dropdown-menu { width: auto; min-width: 160px; margin-top: 4px; diff --git a/app/assets/stylesheets/framework/issue_box.scss b/app/assets/stylesheets/framework/issue_box.scss index d8c57a0e2d9..1d247671761 100644 --- a/app/assets/stylesheets/framework/issue_box.scss +++ b/app/assets/stylesheets/framework/issue_box.scss @@ -11,7 +11,7 @@ padding: 5px 11px; margin-top: 4px; /* Small devices (tablets, 768px and up) */ - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { padding: 0 $gl-btn-padding; margin-top: 5px; } diff --git a/app/assets/stylesheets/framework/layout.scss b/app/assets/stylesheets/framework/layout.scss index d107422e517..0536c39cee7 100644 --- a/app/assets/stylesheets/framework/layout.scss +++ b/app/assets/stylesheets/framework/layout.scss @@ -15,7 +15,7 @@ body { background-color: $white-light !important; } - &.card-content { + &.board-card-content { background-color: $gray-darker; .content-wrapper { @@ -74,7 +74,7 @@ body { } /* Center alert text and alert action links on smaller screens */ - @media (max-width: $screen-sm-max) { + @include media-breakpoint-down(sm) { .alert { text-align: center; } diff --git a/app/assets/stylesheets/framework/lists.scss b/app/assets/stylesheets/framework/lists.scss index f1a8a46dda4..17f4958d535 100644 --- a/app/assets/stylesheets/framework/lists.scss +++ b/app/assets/stylesheets/framework/lists.scss @@ -2,7 +2,7 @@ * Well styled list * */ -.well-list { +.card-body-list { position: relative; margin: 0; padding: 0; @@ -72,7 +72,7 @@ } } - .well-title { + .card.card-body-title { font-size: $list-font-size; line-height: 18px; } @@ -159,7 +159,7 @@ ul.content-list { &:last-child { margin-right: 0; - @media(max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { margin: 0 auto; } } @@ -173,7 +173,7 @@ ul.content-list { .member-controls { float: none; - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { float: right; } } @@ -228,7 +228,7 @@ ul.content-list { } } - .label-default { + .badge-secondary { color: $gl-text-color-secondary; } @@ -237,7 +237,7 @@ ul.content-list { } } -.panel > .content-list > li { +.card > .content-list > li { padding: $gl-padding-top $gl-padding; } @@ -279,251 +279,14 @@ ul.indent-list { padding: 10px 0 0 30px; } - // Specific styles for tree list @keyframes spin-avatar { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } -.groups-list-tree-container { - .has-no-search-results { - text-align: center; - padding: $gl-padding; - font-style: italic; - color: $well-light-text-color; - } - - > .group-list-tree > .group-row.has-children:first-child { - border-top: 0; - } -} - -.group-list-tree { - .avatar-container.content-loading { - position: relative; - - > a, - > a .avatar { - height: 100%; - border-radius: 50%; - } - - > a { - padding: 2px; - - .avatar { - border: 2px solid $white-normal; - - &.identicon { - line-height: 15px; - } - } - } - - &::after { - content: ""; - position: absolute; - height: 100%; - width: 100%; - background-color: transparent; - border: 2px outset $kdb-border; - border-radius: 50%; - animation: spin-avatar 3s infinite linear; - } - } - - .folder-toggle-wrap { - float: left; - line-height: $list-text-height; - font-size: 0; - - span { - font-size: $gl-font-size; - } - } - - .folder-caret, - .item-type-icon { - display: inline-block; - } - - .folder-caret { - width: 15px; - - svg { - margin-bottom: 2px; - } - } - - .item-type-icon { - margin-top: 2px; - width: 20px; - } - - > .group-row:not(.has-children) { - .folder-caret { - opacity: 0; - } - } - - .content-list li:last-child { - padding-bottom: 0; - } - - .group-list-tree { - margin-bottom: 0; - margin-left: 30px; - position: relative; - - &::before { - content: ''; - display: block; - width: 0; - position: absolute; - top: 5px; - bottom: 0; - left: -16px; - border-left: 2px solid $border-white-normal; - } - - .group-row { - position: relative; - - &::before { - content: ""; - display: block; - width: 10px; - height: 0; - border-top: 2px solid $border-white-normal; - position: absolute; - top: 30px; - left: -16px; - } - - &:last-child::before { - background: $white-light; - height: auto; - top: 30px; - bottom: 0; - } - - &.being-removed { - opacity: 0.5; - } - } - } - - .group-row { - padding: 0; - - &.has-children { - border-top: 0; - } - - &:first-child { - border-top: 1px solid $white-normal; - } - - &:last-of-type { - .group-row-contents:not(:hover) { - border-bottom: 1px solid transparent; - } - } - } - - .group-row-contents { - padding: 10px 10px 8px; - border-top: solid 1px transparent; - border-bottom: solid 1px $white-normal; - - &:hover { - border-color: $row-hover-border; - background-color: $row-hover; - cursor: pointer; - } - - .avatar-container > a { - width: 100%; - text-decoration: none; - } - - &.has-more-items { - display: block; - padding: 20px 10px; - } - - .stats { - position: relative; - line-height: 46px; - - > span { - display: inline-flex; - align-items: center; - height: 16px; - min-width: 30px; - } - - > span:last-child { - margin-right: 0; - } - - .stat-value { - margin: 2px 0 0 5px; - } - } - - .controls { - margin-left: 5px; - - > .btn { - margin-right: $btn-xs-side-margin; - } - } - } - - .project-row-contents .stats { - line-height: inherit; - - > span:first-child { - margin-left: 25px; - } - - .item-visibility { - margin-right: 0; - } - - .last-updated { - position: absolute; - right: 12px; - min-width: 250px; - text-align: right; - color: $gl-text-color-secondary; - } - } -} - .namespace-title { .tooltip-inner { max-width: 350px; } } - -ul.group-list-tree { - li.group-row { - > .group-row-contents .title { - line-height: $list-text-height; - } - - &.has-description > .group-row-contents .title { - line-height: inherit; - } - } -} - -.js-groups-list-holder { - .groups-list-loading { - font-size: 34px; - text-align: center; - } -} diff --git a/app/assets/stylesheets/framework/markdown_area.scss b/app/assets/stylesheets/framework/markdown_area.scss index 7b5d1c2cf8b..b893151e4fe 100644 --- a/app/assets/stylesheets/framework/markdown_area.scss +++ b/app/assets/stylesheets/framework/markdown_area.scss @@ -74,7 +74,7 @@ } .md-header-tab { - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { flex: 1; width: 100%; border-bottom: 1px solid $border-color; @@ -90,7 +90,7 @@ &.active { display: block; - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { flex: none; display: flex; justify-content: center; @@ -192,7 +192,7 @@ margin-left: $gl-padding; margin-right: -5px; - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { margin-left: 0; margin-right: 0; } @@ -268,7 +268,7 @@ } } -@media (max-width: $screen-xs-max) { +@include media-breakpoint-down(xs) { .atwho-view-ul { width: 350px; } diff --git a/app/assets/stylesheets/framework/mixins.scss b/app/assets/stylesheets/framework/mixins.scss index 9ff24ebc127..0ea0b65b95f 100644 --- a/app/assets/stylesheets/framework/mixins.scss +++ b/app/assets/stylesheets/framework/mixins.scss @@ -210,3 +210,15 @@ margin-left: -$size; } } + +/* + * Mixin that fixes wrapping issues with long strings (e.g. URLs) + * + * Note: the width needs to be set for it to work in Firefox + */ +@mixin overflow-break-word { + overflow-wrap: break-word; + word-wrap: break-word; + word-break: break-word; + max-width: 100%; +} diff --git a/app/assets/stylesheets/framework/mobile.scss b/app/assets/stylesheets/framework/mobile.scss index 9e03bb98b8e..6244fb86fea 100644 --- a/app/assets/stylesheets/framework/mobile.scss +++ b/app/assets/stylesheets/framework/mobile.scss @@ -1,5 +1,5 @@ /** Common mobile (screen XS, SM) styles **/ -@media (max-width: $screen-xs-max) { +@include media-breakpoint-down(xs) { .container .content { margin-top: 20px; } @@ -14,7 +14,7 @@ font-size: 12px; margin-right: 3px; - .badge { + .badge.badge-pill { display: none; } } @@ -86,7 +86,7 @@ } } -@media (max-width: $screen-sm-max) { +@include media-breakpoint-down(sm) { .issues-filters { .milestone-filter { display: none; diff --git a/app/assets/stylesheets/framework/modal.scss b/app/assets/stylesheets/framework/modal.scss index eb789cc64b0..667661d8b5c 100644 --- a/app/assets/stylesheets/framework/modal.scss +++ b/app/assets/stylesheets/framework/modal.scss @@ -46,7 +46,7 @@ margin-left: $grid-size; } - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { flex-direction: column; .btn + .btn { @@ -55,7 +55,7 @@ } } - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { .btn:first-of-type { margin-left: auto; } @@ -74,7 +74,7 @@ body.modal-open { } } -@media (min-width: $screen-lg-min) { +@include media-breakpoint-up(lg) { .modal-full { width: 98%; } @@ -84,7 +84,7 @@ body.modal-open { background-color: $black-transparent; z-index: 2100; - @media (min-width: $screen-md-min) { + @include media-breakpoint-up(md) { .modal-dialog { margin: 30px auto; } diff --git a/app/assets/stylesheets/framework/page_header.scss b/app/assets/stylesheets/framework/page_header.scss index 0c879f40930..660e3dcac8d 100644 --- a/app/assets/stylesheets/framework/page_header.scss +++ b/app/assets/stylesheets/framework/page_header.scss @@ -3,7 +3,7 @@ padding: 10px 0; margin-bottom: 0; - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { display: flex; align-items: center; @@ -19,7 +19,7 @@ margin-right: 3px; } - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { .btn { width: 100%; margin-top: 10px; @@ -35,7 +35,7 @@ @extend .avatar-inline; margin-left: 0; - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { margin-left: 4px; } } diff --git a/app/assets/stylesheets/framework/pagination.scss b/app/assets/stylesheets/framework/pagination.scss index c3ec9db0f07..d3e013590b6 100644 --- a/app/assets/stylesheets/framework/pagination.scss +++ b/app/assets/stylesheets/framework/pagination.scss @@ -6,6 +6,7 @@ .pagination { padding: 0; + margin: 20px 0; a { cursor: pointer; @@ -30,7 +31,7 @@ } } -.panel > .gl-pagination { +.card > .gl-pagination { margin: 0; } @@ -44,7 +45,7 @@ display: none; } - .page { + .page-item { display: none; &.active { @@ -57,13 +58,13 @@ /** * Small screen pagination */ -@media (max-width: $screen-xs-min) { +@include media-breakpoint-down(xs) { .gl-pagination { .pagination li a { padding: 6px 10px; } - .page { + .page-item { display: none; &.active { @@ -76,9 +77,9 @@ /** * Medium screen pagination */ -@media (min-width: $screen-xs-min) and (max-width: $screen-md-max) { +@media (min-width: map-get($grid-breakpoints, xs)) and (max-width: map-get($grid-breakpoints, sm)) { .gl-pagination { - .page { + .page-item { display: none; &.active, diff --git a/app/assets/stylesheets/framework/panels.scss b/app/assets/stylesheets/framework/panels.scss index e8d69e62194..a8e28104a94 100644 --- a/app/assets/stylesheets/framework/panels.scss +++ b/app/assets/stylesheets/framework/panels.scss @@ -1,14 +1,14 @@ -.panel { +.card { margin-bottom: $gl-padding; } -.panel-slim { - @extend .panel; +.card-slim { + @extend .card; margin-bottom: $gl-vert-padding; } -.panel-heading { +.card-header { padding: $gl-vert-padding $gl-padding; line-height: 36px; @@ -21,7 +21,7 @@ line-height: 20px; } - .badge { + .badge.badge-pill { margin-top: -2px; margin-left: 5px; } @@ -41,12 +41,13 @@ } } -.panel-empty-heading { +.card-empty-heading { border-bottom: 0; } -.panel-body { +.card-body { padding: $gl-padding; + background-color: $white-light; .form-actions { margin: -$gl-padding; @@ -54,7 +55,7 @@ } } -.panel-title { +.card-title { font-size: inherit; line-height: inherit; } diff --git a/app/assets/stylesheets/framework/responsive_tables.scss b/app/assets/stylesheets/framework/responsive_tables.scss index 34fccf6f0a4..764bebd82c6 100644 --- a/app/assets/stylesheets/framework/responsive_tables.scss +++ b/app/assets/stylesheets/framework/responsive_tables.scss @@ -6,7 +6,7 @@ .gl-responsive-table-row-layout { width: 100%; - @media (min-width: $screen-md-min) { + @include media-breakpoint-up(md) { display: flex; align-items: center; @@ -21,7 +21,7 @@ margin-top: 10px; border: 1px solid $border-color; - @media (min-width: $screen-md-min) { + @include media-breakpoint-up(md) { margin: 0; padding: $gl-padding 0; border: 0; @@ -44,13 +44,13 @@ &.section-#{$width} { flex: 0 0 #{$width + '%'}; - @media (min-width: $screen-md-min) { + @include media-breakpoint-up(md) { max-width: #{$width + '%'}; } } } - @media (max-width: $screen-sm-max) { + @include media-breakpoint-down(sm) { display: flex; align-self: stretch; padding: 10px; @@ -65,7 +65,7 @@ &.section-wrap { white-space: normal; - @media (max-width: $screen-sm-max) { + @include media-breakpoint-down(sm) { flex-wrap: wrap; } } @@ -76,11 +76,11 @@ } .table-button-footer { - @media (min-width: $screen-md-min) { + @include media-breakpoint-up(md) { text-align: right; } - @media (max-width: $screen-sm-max) { + @include media-breakpoint-down(sm) { display: block; align-self: stretch; min-height: 0; @@ -122,7 +122,7 @@ .table-row-header { font-size: 13px; - @media (max-width: $screen-sm-max) { + @include media-breakpoint-down(sm) { display: none; } } @@ -132,13 +132,13 @@ color: $gl-text-color-secondary; text-align: left; - @media (min-width: $screen-md-min) { + @include media-breakpoint-up(md) { display: none; } } .table-mobile-content { - @media (max-width: $screen-sm-max) { + @include media-breakpoint-down(sm) { @include flex-max-width(60); text-align: right; } @@ -154,7 +154,7 @@ overflow: hidden; text-overflow: ellipsis; - @media (min-width: $screen-md-min) { + @include media-breakpoint-up(md) { flex: 0 0 90%; } diff --git a/app/assets/stylesheets/framework/secondary_navigation_elements.scss b/app/assets/stylesheets/framework/secondary_navigation_elements.scss index 66dbe403385..c3c64adf3da 100644 --- a/app/assets/stylesheets/framework/secondary_navigation_elements.scss +++ b/app/assets/stylesheets/framework/secondary_navigation_elements.scss @@ -27,18 +27,18 @@ color: $black; border-bottom: 2px solid $gray-darkest; - .badge { + .badge.badge-pill { color: $black; } } - } - - &.active a { - color: $black; - font-weight: $gl-font-weight-bold; - .badge { + &.active { color: $black; + font-weight: $gl-font-weight-bold; + + .badge.badge-pill { + color: $black; + } } } } @@ -56,7 +56,7 @@ white-space: normal; /* Small devices (phones, tablets, 768px and lower) */ - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { width: 100%; } } @@ -80,7 +80,7 @@ } /* Small devices (phones, tablets, 768px and lower) */ - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { width: 100%; &.mobile-separator { @@ -124,21 +124,13 @@ position: relative; /* Medium devices (desktops, 992px and up) */ - @media (min-width: $screen-md-min) { width: 200px; } + @include media-breakpoint-up(md) { width: 200px; } /* Large devices (large desktops, 1200px and up) */ - @media (min-width: $screen-lg-min) { width: 250px; } - - &.input-short { - /* Medium devices (desktops, 992px and up) */ - @media (min-width: $screen-md-min) { width: 170px; } - - /* Large devices (large desktops, 1200px and up) */ - @media (min-width: $screen-lg-min) { width: 210px; } - } + @include media-breakpoint-up(lg) { width: 250px; } } - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { padding-bottom: 0; width: 100%; @@ -164,10 +156,6 @@ } } - .input-short { - width: 100%; - } - .icon-label { display: inline-block; } @@ -184,7 +172,7 @@ .nav-controls { width: auto; - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { width: 100%; } } @@ -204,7 +192,7 @@ width: 100%; } - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { flex-flow: row wrap; .nav-controls { @@ -364,7 +352,7 @@ max-width: 300px; width: auto; - @media(max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { max-width: 250px; } } diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss index 64fff7463d2..8c716400913 100644 --- a/app/assets/stylesheets/framework/sidebar.scss +++ b/app/assets/stylesheets/framework/sidebar.scss @@ -31,7 +31,7 @@ .right-sidebar-collapsed { padding-right: 0; - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { &:not(.wiki-sidebar):not(.build-sidebar):not(.issuable-bulk-update-sidebar) .content-wrapper { padding-right: $gutter_collapsed_width; } @@ -65,13 +65,13 @@ display: inline-flex; } - @media (min-width: $screen-sm-min) and (max-width: $screen-sm-max) { + @include media-breakpoint-only(sm) { &:not(.wiki-sidebar):not(.build-sidebar):not(.issuable-bulk-update-sidebar) .content-wrapper { padding-right: $gutter_collapsed_width; } } - @media (min-width: $screen-md-min) { + @include media-breakpoint-up(md) { .content-wrapper { padding-right: $gutter_width; } diff --git a/app/assets/stylesheets/framework/snippets.scss b/app/assets/stylesheets/framework/snippets.scss index 606d4675f19..f80e9b1014b 100644 --- a/app/assets/stylesheets/framework/snippets.scss +++ b/app/assets/stylesheets/framework/snippets.scss @@ -40,7 +40,7 @@ } .snippet-actions { - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { float: right; } } @@ -67,7 +67,8 @@ padding: 8px 40px; } - .embed-toggle { + .embed-toggle, + .snippet-clipboard-btn { height: 35px; } } diff --git a/app/assets/stylesheets/framework/tables.scss b/app/assets/stylesheets/framework/tables.scss index 5bde96caf42..a10bd1544c5 100644 --- a/app/assets/stylesheets/framework/tables.scss +++ b/app/assets/stylesheets/framework/tables.scss @@ -48,7 +48,7 @@ table { } .responsive-table { - @media (max-width: $screen-sm-max) { + @include media-breakpoint-down(sm) { th { width: 100%; } diff --git a/app/assets/stylesheets/framework/tabs.scss b/app/assets/stylesheets/framework/tabs.scss index c8ba14b7066..6b60149fbbb 100644 --- a/app/assets/stylesheets/framework/tabs.scss +++ b/app/assets/stylesheets/framework/tabs.scss @@ -1,6 +1,7 @@ .gitlab-tabs { background: $gray-light; border: 1px solid $border-color; + flex-wrap: nowrap; li { width: 50%; diff --git a/app/assets/stylesheets/framework/timeline.scss b/app/assets/stylesheets/framework/timeline.scss index 373f35e71d8..75c11590547 100644 --- a/app/assets/stylesheets/framework/timeline.scss +++ b/app/assets/stylesheets/framework/timeline.scss @@ -4,7 +4,7 @@ padding: 0; &::before { - @include notes-media('max', $screen-xs-min) { + @include notes-media('max', map-get($grid-breakpoints, xs)) { background: none; } } @@ -34,7 +34,7 @@ .timeline-entry-inner { position: relative; - @include notes-media('max', $screen-xs-min) { + @include notes-media('max', map-get($grid-breakpoints, xs)) { .timeline-icon { display: none; } diff --git a/app/assets/stylesheets/framework/toggle.scss b/app/assets/stylesheets/framework/toggle.scss index 0cd83df218f..d5cc78a6680 100644 --- a/app/assets/stylesheets/framework/toggle.scss +++ b/app/assets/stylesheets/framework/toggle.scss @@ -121,7 +121,7 @@ cursor: not-allowed; } - @media (max-width: $screen-xs-min) { + @include media-breakpoint-down(xs) { width: 50px; &::before, diff --git a/app/assets/stylesheets/framework/tw_bootstrap.scss b/app/assets/stylesheets/framework/tw_bootstrap.scss deleted file mode 100644 index 1c6e2bf3074..00000000000 --- a/app/assets/stylesheets/framework/tw_bootstrap.scss +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Twitter bootstrap with GitLab customizations/additions - * - */ - -// Core variables and mixins -@import "bootstrap/variables"; -@import "bootstrap/mixins"; - -// Reset -@import "bootstrap/normalize"; -@import "bootstrap/print"; - -// Core CSS -@import "bootstrap/scaffolding"; -@import "bootstrap/type"; -@import "bootstrap/code"; -@import "bootstrap/grid"; -@import "bootstrap/tables"; -@import "bootstrap/forms"; -@import "bootstrap/buttons"; - -// Components -@import "bootstrap/component-animations"; -// @import "bootstrap/dropdowns"; -@import "bootstrap/button-groups"; -@import "bootstrap/input-groups"; -@import "bootstrap/navs"; -@import "bootstrap/navbar"; -@import "bootstrap/breadcrumbs"; -@import "bootstrap/pagination"; -@import "bootstrap/pager"; -@import "bootstrap/labels"; -@import "bootstrap/badges"; -@import "bootstrap/alerts"; -@import "bootstrap/progress-bars"; -@import "bootstrap/list-group"; -@import "bootstrap/wells"; -@import "bootstrap/close"; -@import "bootstrap/panels"; - -// Components w/ JavaScript -@import "bootstrap/modals"; -@import "bootstrap/tooltip"; -@import "bootstrap/popovers"; - -// Utility classes -.clearfix { - @include clearfix(); -} - -.center-block { - @include center-block(); -} - -.pull-right { - float: right !important; -} - -.pull-left { - float: left !important; -} - -.hide { - display: none; -} - -.show { - display: block !important; -} - -.invisible { - visibility: hidden; -} - -.text-hide { - @include text-hide(); -} - -.hidden { - display: none !important; - visibility: hidden !important; -} - -.affix { - position: fixed; -} - -/* - * Fix <summary> elements on firefox - * See https://github.com/necolas/normalize.css/issues/640 - * and https://github.com/twbs/bootstrap/issues/21060 - * - */ -summary { - display: list-item; -} - -@import "bootstrap/responsive-utilities"; - -// Labels -.label { - padding: 4px 5px; - font-size: 12px; - font-style: normal; - font-weight: $gl-font-weight-normal; - display: inline-block; - - &.label-gray { - background-color: $label-gray-bg; - color: $gl-text-color; - text-shadow: none; - } - - &.label-inverse { - background-color: $label-inverse-bg; - } -} - - -/** - * fix to keep tooltips position in top navigation bar - * - */ -.navbar .nav > li { - position: relative; - white-space: nowrap; -} - -/** - * Add some extra stuff to panels - * - */ - -.panel { - box-shadow: none; - - .panel-body { - form, - pre { - margin: 0; - } - - .form-actions { - margin: -15px; - margin-top: 18px; - } - } - - .panel-footer { - .pagination { - margin: 0; - } - - .btn { - min-width: 124px; - } - - .btn-clipboard { - min-width: 0; - } - } - - &.panel-small { - .panel-heading { - padding: 6px 15px; - font-size: 13px; - font-weight: $gl-font-weight-normal; - - a { - color: $panel-heading-link-color; - } - } - } - - &.panel-without-border { - border: 0; - } - - &.panel-without-margin { - margin: 0; - } -} - -.panel-succes .panel-heading, -.panel-info .panel-heading, -.panel-danger .panel-heading, -.panel-warning .panel-heading, -.panel-primary .panel-heading, -.alert { - a:not(.btn) { - @extend .alert-link; - color: $white-light; - text-decoration: underline; - } -} - -// Prevent datetimes on tooltips to break into two lines -.local-timeago { - white-space: nowrap; -} diff --git a/app/assets/stylesheets/framework/tw_bootstrap_variables.scss b/app/assets/stylesheets/framework/tw_bootstrap_variables.scss deleted file mode 100644 index d04e555769b..00000000000 --- a/app/assets/stylesheets/framework/tw_bootstrap_variables.scss +++ /dev/null @@ -1,199 +0,0 @@ -// Override Bootstrap variables here (defaults from bootstrap-sass v3.3.3): -// For all variables see https://github.com/twbs/bootstrap-sass/blob/master/templates/project/_bootstrap-variables.sass -// -// Variables -// -------------------------------------------------- - - -//== Colors -// -//## Gray and brand colors for use across Bootstrap. - -// $gray-base: #000 -// $gray-darker: lighten($gray-base, 13.5%) // #222 -// $gray-dark: lighten($gray-base, 20%) // #333 -// $gray: lighten($gray-base, 33.5%) // #555 -// $gray-light: lighten($gray-base, 46.7%) // #777 -// $gray-lighter: lighten($gray-base, 93.5%) // #eee - -$brand-primary: $gl-primary; -$brand-success: $gl-success; -$brand-info: $gl-info; -$brand-warning: $gl-warning; -$brand-danger: $gl-danger; - -$border-radius-base: 3px !default; -$border-radius-large: 3px !default; -$border-radius-small: 3px !default; - - -//== Scaffolding -// -$text-color: $gl-text-color; -$link-color: $gl-link-color; -$link-hover-color: $gl-link-hover-color; - - -//== Typography -// -//## Font, line-height, and color for body text, headings, and more. - -$font-family-sans-serif: $regular_font; -$font-family-monospace: $monospace_font; -$font-size-base: $gl-font-size; - - -//== Components -// -//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start). - -$padding-base-vertical: $gl-vert-padding; -$padding-base-horizontal: $gl-padding; -$component-active-color: $white-light; -$component-active-bg: $brand-info; - -//== Forms -// -//## - -$input-color: $text-color; -$input-border: $border-color; -$input-border-focus: $focus-border-color; -$legend-color: $text-color; - - -//== Pagination -// -//## - -$pagination-color: $gl-text-color; -$pagination-bg: $white-light; -$pagination-border: $border-color; - -$pagination-hover-color: $gl-text-color; -$pagination-hover-bg: $row-hover; -$pagination-hover-border: $border-color; - -$pagination-active-color: $white-light; -$pagination-active-bg: $gl-link-color; -$pagination-active-border: $gl-link-color; - -$pagination-disabled-color: #cdcdcd; -$pagination-disabled-bg: $gray-light; -$pagination-disabled-border: $border-color; - - -//== Form states and alerts -// -//## Define colors for form feedback states and, by default, alerts. - -$state-success-text: $white-light; -$state-success-bg: $brand-success; -$state-success-border: $brand-success; - -$state-info-text: $white-light; -$state-info-bg: $brand-info; -$state-info-border: $brand-info; - -$state-warning-text: $white-light; -$state-warning-bg: $brand-warning; -$state-warning-border: $brand-warning; - -$state-danger-text: $white-light; -$state-danger-bg: $brand-danger; -$state-danger-border: $brand-danger; - - -//== Alerts -// -//## Define alert colors, border radius, and padding. - -$alert-border-radius: 0; - - -//== Panels -// -//## - -$panel-border-radius: 2px; -$panel-default-text: $text-color; -$panel-default-border: $border-color; -$panel-default-heading-bg: $gray-light; -$panel-footer-bg: $gray-light; -$panel-inner-border: $border-color; - -$badge-bg: $badge-bg; -$badge-color: $badge-color; - -//== Wells -// -//## - -$well-bg: $gray-light; -$well-border: #eee; - -//== Code -// -//## - -$code-color: $red-600; -$code-bg: lighten($red-100, 2%); - -$kbd-color: $white-light; -$kbd-bg: #333; - -//== Buttons -// -//## -$btn-default-color: $gl-text-color; -$btn-default-bg: $white-light; -$btn-default-border: #e7e9ed; - -//== Nav -// -//## -$nav-link-padding: 13px $gl-padding; - -//== Code -// -//## -$pre-bg: $gray-light !default; -$pre-color: $gl-text-color !default; -$pre-border-color: $border-color; - -$table-bg-accent: $gray-light; - -$zindex-popover: 900; - -//== Modals -// -//## - -//** Padding applied to the modal body -$modal-inner-padding: $gl-padding; - -//** Padding applied to the modal title -$modal-title-padding: $gl-padding; -//** Modal title line-height -// $modal-title-line-height: $line-height-base - -//** Background color of modal content area -$modal-content-bg: $gray-light; -$modal-body-bg: $white-light; -//** Modal content border color -// $modal-content-border-color: rgba(0,0,0,.2) -//** Modal content border color **for IE8** -// $modal-content-fallback-border-color: #999 - -//** Modal backdrop background color -// $modal-backdrop-bg: #000 -//** Modal backdrop opacity -// $modal-backdrop-opacity: .5 -//** Modal header border color -// $modal-header-border-color: #e5e5e5 -//** Modal footer border color -// $modal-footer-border-color: $modal-header-border-color - -$modal-lg: 860px; -$modal-md: 540px; -// $modal-sm: 300px diff --git a/app/assets/stylesheets/framework/typography.scss b/app/assets/stylesheets/framework/typography.scss index 9e1371648ed..ed0bfbbe08b 100644 --- a/app/assets/stylesheets/framework/typography.scss +++ b/app/assets/stylesheets/framework/typography.scss @@ -114,7 +114,7 @@ font-size: 0.95em; } - blockquote { + .blockquote { color: $gl-grayish-blue; font-size: inherit; padding: 8px 24px; @@ -122,12 +122,12 @@ border-left: 3px solid $white-dark; } - blockquote:dir(rtl) { + .blockquote:dir(rtl) { border-left: 0; border-right: 3px solid $white-dark; } - blockquote p { + .blockquote p { color: $gl-grayish-blue !important; font-size: inherit; line-height: 1.5; @@ -321,6 +321,16 @@ h6 { /** CODE **/ pre { font-family: $monospace_font; + display: block; + padding: $gl-padding-8; + margin: 0 0 $gl-padding-8; + font-size: 13px; + word-break: break-all; + word-wrap: break-word; + color: $gl-text-color; + background-color: $gray-light; + border: 1px solid $border-color; + border-radius: $border-radius-small; } code { @@ -391,7 +401,7 @@ h4 { } .text-right-lg { - @media (min-width: $screen-lg-min) { + @include media-breakpoint-up(lg) { text-align: right; } } diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index b5505538541..89b61530ddb 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -142,6 +142,11 @@ $border-gray-normal-dashed: darken($gray-normal, $darken-border-dashed-factor); $border-gray-dark: darken($white-normal, $darken-border-factor); /* + * Override Bootstrap 4 variables + */ +$secondary: $gray-light; + +/* * UI elements */ $border-color: #e5e5e5; @@ -230,7 +235,7 @@ $row-hover: $blue-50; $row-hover-border: $blue-200; $progress-color: #c0392b; $header-height: 40px; -$ide-statusbar-height: 27px; +$ide-statusbar-height: 25px; $fixed-layout-width: 1280px; $limited-layout-width: 990px; $limited-layout-width-sm: 790px; @@ -306,6 +311,11 @@ $gl-warning: $orange-500; $gl-danger: $red-500; $gl-btn-active-background: rgba(0, 0, 0, 0.16); $gl-btn-active-gradient: inset 0 2px 3px $gl-btn-active-background; +// Bootstrap override states +$success: $gl-success; +$info: $gl-info; +$warning: $gl-warning; +$danger: $gl-danger; /* * Commit Diff Colors @@ -554,6 +564,8 @@ $input-danger-border: $red-400; $input-group-addon-bg: #f7f8fa; $gl-field-focus-shadow: rgba(0, 0, 0, 0.075); $gl-field-focus-shadow-error: rgba($red-500, 0.6); +$input-short-width: 200px; +$input-short-md-width: 280px; /* * Help diff --git a/app/assets/stylesheets/framework/wells.scss b/app/assets/stylesheets/framework/wells.scss index 3fa7a260017..514fac82b1e 100644 --- a/app/assets/stylesheets/framework/wells.scss +++ b/app/assets/stylesheets/framework/wells.scss @@ -5,7 +5,7 @@ border-radius: $border-radius-default; margin-bottom: $gl-padding; - .well-segment { + .card.card-body-segment { padding: $gl-padding; &:not(:last-of-type) { @@ -59,7 +59,7 @@ } } - .label.label-gray { + .label-gray { background-color: $well-expand-item; } @@ -108,7 +108,7 @@ } } -.well-centered { +.card.card-body-centered { h1 { font-weight: $gl-font-weight-normal; text-align: center; diff --git a/app/assets/stylesheets/mailers/highlighted_diff_email.scss b/app/assets/stylesheets/mailers/highlighted_diff_email.scss index 658ac26fca9..b5eda79e5ed 100644 --- a/app/assets/stylesheets/mailers/highlighted_diff_email.scss +++ b/app/assets/stylesheets/mailers/highlighted_diff_email.scss @@ -138,7 +138,7 @@ pre { margin: 0; } -blockquote { +.blockquote { color: $gl-grayish-blue; padding: 0 0 0 15px; margin: 0; diff --git a/app/assets/stylesheets/pages/boards.scss b/app/assets/stylesheets/pages/boards.scss index 681242f8d85..1c3d312f7ac 100644 --- a/app/assets/stylesheets/pages/boards.scss +++ b/app/assets/stylesheets/pages/boards.scss @@ -1,5 +1,3 @@ -@import './issues/issue_count_badge'; - [v-cloak] { display: none; } @@ -60,7 +58,7 @@ .boards-app { position: relative; - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { transition: width $sidebar-transition-duration; width: 100%; @@ -83,11 +81,11 @@ white-space: nowrap; min-height: 200px; - @media (min-width: $screen-sm-min) and (max-width: $screen-sm-max) { + @include media-breakpoint-only(sm) { height: calc(100vh - #{$issue-board-list-difference-sm}); } - @media (min-width: $screen-md-min) { + @include media-breakpoint-up(md) { height: calc(100vh - #{$issue-board-list-difference-md}); } @@ -96,13 +94,13 @@ 100vh - #{$issue-board-list-difference-xs} - #{$performance-bar-height} ); - @media (min-width: $screen-sm-min) and (max-width: $screen-sm-max) { + @include media-breakpoint-only(sm) { height: calc( 100vh - #{$issue-board-list-difference-sm} - #{$performance-bar-height} ); } - @media (min-width: $screen-md-min) { + @include media-breakpoint-up(md) { height: calc( 100vh - #{$issue-board-list-difference-md} - #{$performance-bar-height} ); @@ -119,7 +117,7 @@ white-space: normal; vertical-align: top; - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { width: 400px; } @@ -276,7 +274,7 @@ font-size: (26px / $issue-boards-font-size) * 1em; } -.card { +.board-card { position: relative; padding: 11px 10px 11px $gl-padding; background: $white-light; @@ -284,12 +282,15 @@ box-shadow: 0 1px 2px $issue-boards-card-shadow; list-style: none; + // as a fallback, hide overflow content so that dragging and dropping still works + overflow: hidden; + &:not(:last-child) { margin-bottom: 5px; } &.is-active, - &.is-active .card-assignee:hover a { + &.is-active .board-card-assignee:hover a { background-color: $row-hover; &:first-child:not(:only-child) { @@ -297,7 +298,7 @@ } } - .label { + .badge { border: 0; outline: 0; } @@ -309,24 +310,23 @@ } } -.card-title { +.board-card-title { + @include overflow-break-word(); margin: 0 30px 0 0; font-size: 1em; line-height: inherit; a { color: $gl-text-color; - word-wrap: break-word; - word-break: break-word; margin-right: 2px; } } -.card-header { +.board-card-header { display: flex; min-height: 20px; - .card-assignee { + .board-card-assignee { display: flex; justify-content: flex-end; position: absolute; @@ -397,16 +397,16 @@ } } -.card-footer { +.board-card-footer { margin: 0 0 5px; - .label { + .badge { margin-top: 5px; margin-right: 6px; } } -.card-number { +.board-card-number { font-size: 12px; color: $gl-text-color-secondary; } @@ -462,8 +462,8 @@ } .issuable-header-text { + @include overflow-break-word(); padding-right: 35px; - word-break: break-word; > strong { font-weight: $gl-font-weight-bold; @@ -564,11 +564,11 @@ .add-issues-list-column { width: 100%; - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { width: 50%; } - @media (min-width: $screen-md-min) { + @include media-breakpoint-up(md) { width: (100% / 3); } } @@ -583,11 +583,11 @@ margin-right: -$gl-vert-padding; overflow-y: scroll; - .card-parent { + .board-card-parent { padding: 0 5px 5px; } - .card { + .board-card { border: 1px solid $border-gray-dark; box-shadow: 0 1px 2px rgba($issue-boards-card-shadow, 0.3); cursor: pointer; @@ -637,7 +637,7 @@ display: none; margin-right: 10px; - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { display: block; } } @@ -645,7 +645,7 @@ .dropdown-menu-toggle { width: 100px; - @media (min-width: $screen-md-min) { + @include media-breakpoint-up(md) { width: 140px; } } diff --git a/app/assets/stylesheets/pages/builds.scss b/app/assets/stylesheets/pages/builds.scss index 50f32660445..9ee02ca1d83 100644 --- a/app/assets/stylesheets/pages/builds.scss +++ b/app/assets/stylesheets/pages/builds.scss @@ -215,7 +215,7 @@ } .header-action-buttons { - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { .sidebar-toggle-btn { margin-top: 0; margin-left: 10px; @@ -277,10 +277,6 @@ &.coverage { padding: 0 16px 11px; } - - .btn-group-justified { - margin-top: 5px; - } } .block-last { @@ -305,7 +301,7 @@ background-color: $white-light; } - .label { + .badge.badge-pill { margin-left: 2px; } @@ -320,7 +316,7 @@ } } - @media (max-width: $screen-sm-max) { + @include media-breakpoint-down(sm) { display: block; .btn { diff --git a/app/assets/stylesheets/pages/clusters.scss b/app/assets/stylesheets/pages/clusters.scss index 3fd13078131..2b6d92016d5 100644 --- a/app/assets/stylesheets/pages/clusters.scss +++ b/app/assets/stylesheets/pages/clusters.scss @@ -63,7 +63,7 @@ text-decoration: none; } - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { > div { display: flex; align-items: center; diff --git a/app/assets/stylesheets/pages/commits.scss b/app/assets/stylesheets/pages/commits.scss index 944996159d7..a4ca82de90e 100644 --- a/app/assets/stylesheets/pages/commits.scss +++ b/app/assets/stylesheets/pages/commits.scss @@ -23,7 +23,7 @@ } .commit-hash-full { - @media (max-width: $screen-sm-max) { + @include media-breakpoint-down(sm) { width: 80px; white-space: nowrap; overflow: hidden; @@ -183,7 +183,7 @@ } .commit-actions { - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { .fa-spinner { font-size: 12px; } @@ -327,8 +327,12 @@ } &.invalid { - @include status-color($gray-dark, $gray, $gray-darkest); + @include status-color($gray-dark, color("gray"), $gray-darkest); border-color: $gray-darkest; + + &:not(span):hover { + color: color("gray"); + } } } diff --git a/app/assets/stylesheets/pages/convdev_index.scss b/app/assets/stylesheets/pages/convdev_index.scss index fb1899284fd..bd338326154 100644 --- a/app/assets/stylesheets/pages/convdev_index.scss +++ b/app/assets/stylesheets/pages/convdev_index.scss @@ -53,19 +53,19 @@ $space-between-cards: 8px; padding: $space-between-cards / 2; position: relative; - @media (min-width: $screen-xs-min) { + @include media-breakpoint-up(xs) { width: percentage(1 / 4); } - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { width: percentage(1 / 5); } - @media (min-width: $screen-md-min) { + @include media-breakpoint-up(md) { width: percentage(1 / 6); } - @media (min-width: $screen-lg-min) { + @include media-breakpoint-up(lg) { width: percentage(1 / 10); } } @@ -82,7 +82,7 @@ $space-between-cards: 8px; .convdev-card-low { border-top-color: $color-low-score; - .card-score-big { + .board-card-score-big { background-color: $red-50; } } @@ -90,7 +90,7 @@ $space-between-cards: 8px; .convdev-card-average { border-top-color: $color-average-score; - .card-score-big { + .board-card-score-big { background-color: $orange-50; } } @@ -98,7 +98,7 @@ $space-between-cards: 8px; .convdev-card-high { border-top-color: $color-high-score; - .card-score-big { + .board-card-score-big { background-color: $green-50; } } @@ -112,14 +112,14 @@ $space-between-cards: 8px; margin: 0 0 2px; } - .text-light { + .light-text { font-size: 13px; line-height: 1.25; color: $gl-text-color-secondary; } } -.card-scores { +.board-card-scores { display: flex; justify-content: space-around; align-items: center; @@ -127,22 +127,22 @@ $space-between-cards: 8px; line-height: 1; } -.card-score { +.board-card-score { color: $gl-text-color-secondary; - .card-score-name { + .board-card-score-name { font-size: 13px; margin-top: 4px; } } -.card-score-value { +.board-card-score-value { font-size: 16px; color: $gl-text-color; font-weight: $gl-font-weight-normal; } -.card-score-big { +.board-card-score-big { border-top: 2px solid $border-color; border-bottom: 1px solid $border-color; font-size: 22px; @@ -150,7 +150,7 @@ $space-between-cards: 8px; font-weight: $gl-font-weight-normal; } -.card-buttons { +.board-card-buttons { display: flex; > * { diff --git a/app/assets/stylesheets/pages/cycle_analytics.scss b/app/assets/stylesheets/pages/cycle_analytics.scss index cfef6476d4d..a22c666a525 100644 --- a/app/assets/stylesheets/pages/cycle_analytics.scss +++ b/app/assets/stylesheets/pages/cycle_analytics.scss @@ -15,7 +15,7 @@ max-width: 480px; padding: 0 $gl-padding; - @media (max-width: $screen-sm-min) { + @include media-breakpoint-down(sm) { margin: 0 auto; } } @@ -75,13 +75,13 @@ } } - .panel { + .card { .content-block { padding: 24px 0; border-bottom: 0; position: relative; - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { padding: 6px 0 24px; } } @@ -89,7 +89,7 @@ .column { text-align: center; - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { padding: 15px 0; } @@ -106,7 +106,7 @@ } &:last-child { - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { text-align: center; } } @@ -213,7 +213,7 @@ .stage-panel { min-width: 968px; - .panel-heading { + .card-header { padding: 0; background-color: transparent; } @@ -266,7 +266,9 @@ &.issue-title, &.commit-title, &.merge-merquest-title { - @include text-overflow(); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; max-width: 100%; display: block; diff --git a/app/assets/stylesheets/pages/detail_page.scss b/app/assets/stylesheets/pages/detail_page.scss index 2f2c04206e2..7b36bcb3c7d 100644 --- a/app/assets/stylesheets/pages/detail_page.scss +++ b/app/assets/stylesheets/pages/detail_page.scss @@ -14,7 +14,7 @@ white-space: nowrap; } - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { display: block; } } @@ -25,7 +25,7 @@ display: flex; flex-grow: 1; - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { padding-left: 0; padding-right: 0; } @@ -36,7 +36,7 @@ flex-shrink: 0; flex: 0 0 auto; - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { width: 100%; margin-top: 10px; diff --git a/app/assets/stylesheets/pages/diff.scss b/app/assets/stylesheets/pages/diff.scss index 70ce5de6a6c..f06c9dcdf8c 100644 --- a/app/assets/stylesheets/pages/diff.scss +++ b/app/assets/stylesheets/pages/diff.scss @@ -86,13 +86,13 @@ &.left-side-selected { td.line_content.parallel.right-side { - @include user-select(none); + user-select: none; } } &.right-side-selected { td.line_content.parallel.left-side { - @include user-select(none); + user-select: none; } } } @@ -109,7 +109,7 @@ .old_line, .new_line { - @include user-select(none); + user-select: none; margin: 0; border: 0; padding: 0 5px; @@ -592,14 +592,14 @@ } .commit-stat-summary { - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { margin-left: -$gl-padding; padding-left: $gl-padding; background-color: $white-light; } } - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { position: -webkit-sticky; position: sticky; top: 24px; @@ -610,10 +610,6 @@ top: 76px; } - &:not(.is-stuck) .diff-stats-additions-deletions-collapsed { - display: none; - } - &.is-stuck { padding-top: 0; padding-bottom: 0; @@ -622,13 +618,21 @@ .diff-stats-additions-deletions-expanded, .inline-parallel-buttons { - display: none; + display: none !important; + } + } + } + + @include media-breakpoint-up(lg) { + &.is-stuck { + .diff-stats-additions-deletions-collapsed { + display: block !important; } } } } -@media (min-width: $screen-sm-min) { +@include media-breakpoint-up(sm) { .with-performance-bar { .diff-files-changed.diff-files-changed-merge-request { top: 76px + $performance-bar-height; @@ -641,7 +645,7 @@ width: 100%; z-index: 150; - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { left: $gl-padding; } @@ -772,9 +776,9 @@ } } -.frame .badge, -.image-diff-avatar-link .badge, -.notes > .badge { +.frame .badge.badge-pill, +.image-diff-avatar-link .badge.badge-pill, +.notes > .badge.badge-pill { position: absolute; background-color: $blue-400; color: $white-light; @@ -788,7 +792,7 @@ } } -.frame .badge, +.frame .badge.badge-pill, .frame .image-comment-badge { // Center align badges on the frame transform: translate(-50%, -50%); @@ -811,14 +815,14 @@ .image-diff-avatar-link { position: relative; - .badge, + .badge.badge-pill, .image-comment-badge { top: 25px; right: 8px; } } -.notes > .badge { +.notes > .badge.badge-pill { display: none; left: -13px; } @@ -840,7 +844,7 @@ display: none; } - .notes > .badge { + .notes > .badge.badge-pill { display: block; } } diff --git a/app/assets/stylesheets/pages/editor.scss b/app/assets/stylesheets/pages/editor.scss index 8ecda50602d..437621299e0 100644 --- a/app/assets/stylesheets/pages/editor.scss +++ b/app/assets/stylesheets/pages/editor.scss @@ -37,7 +37,7 @@ padding-top: 7px; padding-bottom: 7px; - .pull-right { + .float-right { height: 20px; } } @@ -63,11 +63,11 @@ max-width: 450px; float: left; - @media(max-width: $screen-md-max) { + @media(max-width: map-get($grid-breakpoints, lg)-1) { width: 280px; } - @media(max-width: $screen-sm-max) { + @media(max-width: map-get($grid-breakpoints, md)-1) { width: 180px; } } @@ -111,10 +111,10 @@ } -@media(max-width: $screen-xs-max){ +@include media-breakpoint-down(xs) { .file-editor { .file-title { - .pull-right { + .float-right { height: auto; } } @@ -153,7 +153,7 @@ vertical-align: top; display: inline-block; - @media(max-width: $screen-sm-max) { + @media(max-width: map-get($grid-breakpoints, md)-1) { display: block; margin: 19px 0 12px; } @@ -166,7 +166,7 @@ padding: 0 0 0 14px; border-left: 1px solid $border-color; - @media(max-width: $screen-sm-max) { + @media(max-width: map-get($grid-breakpoints, md)-1) { display: block; width: 100%; margin: 5px 0; @@ -181,7 +181,7 @@ margin-top: 6px; line-height: 21px; - @media(max-width: $screen-sm-max) { + @media(max-width: map-get($grid-breakpoints, md)-1) { display: block; margin: 5px 0; } @@ -193,7 +193,7 @@ vertical-align: top; margin: 5px 0 0 8px; - @media(max-width: $screen-sm-max) { + @media(max-width: map-get($grid-breakpoints, md)-1) { display: block; width: 100%; margin: 0 0 16px; @@ -209,7 +209,7 @@ font-family: $regular_font; margin-top: -5px; - @media(max-width: $screen-sm-max) { + @media(max-width: map-get($grid-breakpoints, md)-1) { display: block; width: 100%; margin: 5px 0; @@ -223,7 +223,7 @@ width: 250px; vertical-align: top; - @media(max-width: $screen-sm-max) { + @media(max-width: map-get($grid-breakpoints, md)-1) { display: block; width: 100%; margin: 5px 0; @@ -237,7 +237,7 @@ display: inline-block; margin: 7px 0 0 10px; - @media(max-width: $screen-sm-max) { + @media(max-width: map-get($grid-breakpoints, md)-1) { display: block; width: 100%; margin: 20px 0; diff --git a/app/assets/stylesheets/pages/environments.scss b/app/assets/stylesheets/pages/environments.scss index 1f406cc1c2d..cd0d67613c3 100644 --- a/app/assets/stylesheets/pages/environments.scss +++ b/app/assets/stylesheets/pages/environments.scss @@ -1,4 +1,4 @@ -@media (max-width: $screen-md-max) { +@include media-breakpoint-down(md) { .deployments-container { width: 100%; overflow: auto; @@ -138,7 +138,7 @@ border-left: 0; border-right: 0; - @media (min-width: $screen-sm-max) { + @media (min-width: map-get($grid-breakpoints, md)-1) { border-top: 0; } } @@ -251,7 +251,7 @@ font-size: 16px; } - @media (max-width: $screen-sm-max) { + @include media-breakpoint-down(sm) { min-width: 100%; } } @@ -432,7 +432,7 @@ } } - @media (max-width: $screen-sm-max) { + @include media-breakpoint-down(sm) { .label-axis-text, .text-metric-usage, .legend-axis-text { diff --git a/app/assets/stylesheets/pages/events.scss b/app/assets/stylesheets/pages/events.scss index d9267f5cdf3..f79586b68b9 100644 --- a/app/assets/stylesheets/pages/events.scss +++ b/app/assets/stylesheets/pages/events.scss @@ -70,7 +70,7 @@ .md { font-size: $gl-font-size; - .label { + .badge.badge-pill { color: $gl-text-color; } @@ -173,7 +173,7 @@ } } -@media (max-width: $screen-xs-max) { +@include media-breakpoint-down(xs) { .event-item { padding-left: 0; diff --git a/app/assets/stylesheets/pages/groups.scss b/app/assets/stylesheets/pages/groups.scss index 6ee8b33bd39..c2b42e02eee 100644 --- a/app/assets/stylesheets/pages/groups.scss +++ b/app/assets/stylesheets/pages/groups.scss @@ -2,7 +2,7 @@ @include str-truncated(90%); } -.dashboard .side .panel .panel-heading .input-group { +.dashboard .side .card .card-header .input-group { .form-control { height: 42px; @@ -18,6 +18,10 @@ .group-row { @include basic-list-stats; + + .description p { + margin-bottom: 0; + } } .ldap-group-links { @@ -36,7 +40,7 @@ flex: 1; } - .dropdown-menu-align-right { + .dropdown-menu-right { margin-top: 0; } @@ -98,7 +102,7 @@ } } - @media (max-width: $screen-sm-max) { + @include media-breakpoint-down(sm) { &, .dropdown, .dropdown .dropdown-toggle, @@ -145,14 +149,14 @@ padding: 50px 100px; overflow: hidden; - @media (max-width: $screen-sm-max) { + @include media-breakpoint-down(sm) { padding: 50px 0; } svg { float: right; - @media (max-width: $screen-sm-max) { + @include media-breakpoint-down(sm) { float: none; display: block; width: 250px; @@ -167,7 +171,7 @@ width: 460px; margin-top: 120px; - @media (max-width: $screen-sm-max) { + @include media-breakpoint-down(sm) { float: none; margin-top: 60px; width: auto; @@ -201,7 +205,7 @@ max-width: 480px; padding: 0 $gl-padding; - @media (max-width: $screen-sm-min) { + @include media-breakpoint-down(sm) { margin: 0 auto; } } @@ -237,3 +241,231 @@ overflow-y: unset; } } + +.groups-list-tree-container { + .has-no-search-results { + text-align: center; + padding: $gl-padding; + font-style: italic; + color: $well-light-text-color; + } + + > .group-list-tree > .group-row.has-children:first-child { + border-top: 0; + } +} + +.group-list-tree { + .avatar-container.content-loading { + position: relative; + + > a, + > a .avatar { + height: 100%; + border-radius: 50%; + } + + > a { + padding: 2px; + + .avatar { + border: 2px solid $white-normal; + + &.identicon { + line-height: 15px; + } + } + } + + &::after { + content: ""; + position: absolute; + height: 100%; + width: 100%; + background-color: transparent; + border: 2px outset $kdb-border; + border-radius: 50%; + animation: spin-avatar 3s infinite linear; + } + } + + .folder-toggle-wrap { + float: left; + line-height: $list-text-height; + font-size: 0; + + span { + font-size: $gl-font-size; + } + } + + .folder-caret, + .item-type-icon { + display: inline-block; + } + + .folder-caret { + width: 15px; + + svg { + margin-bottom: 2px; + } + } + + .item-type-icon { + margin-top: 2px; + width: 20px; + } + + > .group-row:not(.has-children) { + .folder-caret { + opacity: 0; + } + } + + .content-list li:last-child { + padding-bottom: 0; + } + + .group-list-tree { + margin-bottom: 0; + margin-left: 30px; + position: relative; + + &::before { + content: ''; + display: block; + width: 0; + position: absolute; + top: 5px; + bottom: 0; + left: -16px; + border-left: 2px solid $border-white-normal; + } + + .group-row { + position: relative; + + &::before { + content: ""; + display: block; + width: 10px; + height: 0; + border-top: 2px solid $border-white-normal; + position: absolute; + top: 30px; + left: -16px; + } + + &:last-child::before { + background: $white-light; + height: auto; + top: 30px; + bottom: 0; + } + + &.being-removed { + opacity: 0.5; + } + } + } + + .group-row { + padding: 0; + + &.has-children { + border-top: 0; + } + + &:first-child { + border-top: 1px solid $white-normal; + } + } + + .group-row-contents { + padding: $gl-padding-top; + + &:hover { + border-color: $row-hover-border; + background-color: $row-hover; + cursor: pointer; + } + + .avatar-container > a { + width: 100%; + text-decoration: none; + } + + &.has-more-items { + display: block; + padding: 20px 10px; + } + + .stats { + position: relative; + line-height: 46px; + + > span { + display: inline-flex; + align-items: center; + height: 16px; + min-width: 30px; + } + + > span:last-child { + margin-right: 0; + } + + .stat-value { + margin: 2px 0 0 5px; + } + } + + .controls { + margin-left: 5px; + + > .btn { + margin-right: $btn-xs-side-margin; + } + } + } + + .project-row-contents .stats { + line-height: inherit; + + > span:first-child { + margin-left: 25px; + } + + .item-visibility { + margin-right: 0; + } + + .last-updated { + position: absolute; + right: 12px; + min-width: 250px; + text-align: right; + color: $gl-text-color-secondary; + } + } +} + +ul.group-list-tree { + li.group-row { + > .group-row-contents .title { + line-height: $list-text-height; + } + + &.has-description > .group-row-contents .title { + line-height: inherit; + } + } +} + +.js-groups-list-holder { + .groups-list-loading { + font-size: 34px; + text-align: center; + } +} diff --git a/app/assets/stylesheets/pages/help.scss b/app/assets/stylesheets/pages/help.scss index 9cc9e11bcd1..0350fe5752e 100644 --- a/app/assets/stylesheets/pages/help.scss +++ b/app/assets/stylesheets/pages/help.scss @@ -28,8 +28,8 @@ } .key { - @extend .label; - @extend .label-inverse; + @extend .badge.badge-pill; + background-color: $label-inverse-bg; font: 11px Consolas, "Liberation Mono", Menlo, Courier, monospace; padding: 3px 5px; } diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index b2dad4a358a..4aea9740735 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -197,9 +197,21 @@ } &.assignee { - .author_link:hover { - .author { - text-decoration: underline; + .author_link { + display: block; + padding-left: 42px; + position: relative; + + &:hover { + .author { + text-decoration: underline; + } + } + + .avatar { + left: 0; + position: absolute; + top: 0; } } } @@ -361,7 +373,7 @@ /* Extra small devices (phones, less than 768px) */ display: none; /* Small devices (tablets, 768px and up) */ - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { display: block; } @@ -644,7 +656,7 @@ } .issuable-form-padding-top { - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { padding-top: 7px; } } @@ -658,7 +670,7 @@ padding-left: 9px; padding-right: 9px; - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { display: inline-block; height: auto; align-self: center; @@ -666,7 +678,7 @@ } .issuable-gutter-toggle { - @media (max-width: $screen-sm-max) { + @include media-breakpoint-down(sm) { margin-left: $btn-side-margin; } } @@ -684,7 +696,7 @@ width: 100%; } - @media (max-width: $screen-sm-max) { + @include media-breakpoint-down(sm) { margin-bottom: $gl-padding; } } @@ -725,7 +737,7 @@ } } - @media(max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { .issuable-meta { .controls li { margin-right: 0; @@ -760,7 +772,7 @@ } } - @media(max-width: $screen-md-max) { + @media(max-width: map-get($grid-breakpoints, lg)-1) { .task-status, .issuable-due-date, .project-ref-path { diff --git a/app/assets/stylesheets/pages/issues.scss b/app/assets/stylesheets/pages/issues.scss index b9390450477..19fb99bfa93 100644 --- a/app/assets/stylesheets/pages/issues.scss +++ b/app/assets/stylesheets/pages/issues.scss @@ -1,5 +1,3 @@ -@import "./issues/issue_count_badge"; - .issues-list { .issue { padding: 10px 0 10px $gl-padding; @@ -143,7 +141,7 @@ ul.related-merge-requests > li { } } -@media (max-width: $screen-xs-max) { +@include media-breakpoint-down(xs) { .detail-page-header { .issuable-meta { line-height: 18px; @@ -205,7 +203,7 @@ ul.related-merge-requests > li { } } - .btn-group:not(.hide) { + .btn-group:not(.hidden) { display: flex; } @@ -247,7 +245,7 @@ ul.related-merge-requests > li { display: block; } -@media (min-width: $screen-sm-min) { +@include media-breakpoint-up(sm) { .emoji-block .row { display: flex; @@ -258,8 +256,8 @@ ul.related-merge-requests > li { } .create-mr-dropdown-wrap { - .btn-group:not(.hide) { - display: inline-block; + .btn-group:not(.hidden) { + display: inline-flex; } } } diff --git a/app/assets/stylesheets/pages/labels.scss b/app/assets/stylesheets/pages/labels.scss index d81236c5883..e178371d21f 100644 --- a/app/assets/stylesheets/pages/labels.scss +++ b/app/assets/stylesheets/pages/labels.scss @@ -62,13 +62,13 @@ display: inline-block; margin-bottom: 10px; - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { width: 200px; margin-left: $gl-padding * 2; margin-bottom: 0; } - .label { + .badge { overflow: hidden; text-overflow: ellipsis; max-width: 100%; @@ -80,7 +80,7 @@ margin-bottom: 10px; margin-left: 50px; - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { display: inline-block; width: 100px; margin-left: 10px; @@ -101,7 +101,7 @@ color: $blue-600; } - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { display: inline-block; max-width: 50%; margin-left: 10px; @@ -110,7 +110,7 @@ } } - .label { + .badge { padding: 4px $grid-size; font-size: $label-font-size; position: relative; @@ -122,6 +122,7 @@ padding: 0 $grid-size; line-height: 16px; border-radius: $label-border-radius; + color: $white-light; } .dropdown-labels-error { @@ -132,7 +133,7 @@ } .manage-labels-list { - @media(min-width: $screen-md-min) { + @media(min-width: map-get($grid-breakpoints, md)) { &.content-list li { padding: $gl-padding 0; } @@ -171,12 +172,12 @@ } .dropdown { - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { float: right; } } - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { .dropdown-menu { min-width: 100%; } @@ -283,7 +284,7 @@ } .label-subscribe-button { - @media(min-width: $screen-md-min) { + @media(min-width: map-get($grid-breakpoints, md)) { min-width: 105px; margin-left: $gl-padding; } diff --git a/app/assets/stylesheets/pages/login.scss b/app/assets/stylesheets/pages/login.scss index 97303d02666..c1b1d2e028d 100644 --- a/app/assets/stylesheets/pages/login.scss +++ b/app/assets/stylesheets/pages/login.scss @@ -191,9 +191,9 @@ } } -@media (max-width: $screen-xs-max) { +@include media-breakpoint-down(xs) { .login-page { - .col-sm-5.pull-right { + .col-md-5.float-right { float: none !important; margin-bottom: 45px; } @@ -243,7 +243,7 @@ .navless-container { padding: 65px 15px; // height of footer + bottom padding of email confirmation link - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { padding: 0 15px 65px; } } diff --git a/app/assets/stylesheets/pages/members.scss b/app/assets/stylesheets/pages/members.scss index 3422829de58..de2b5701e2d 100644 --- a/app/assets/stylesheets/pages/members.scss +++ b/app/assets/stylesheets/pages/members.scss @@ -9,9 +9,13 @@ } } +.member-sort-dropdown { + margin-left: $gl-padding-8; +} + .member { .list-item-name { - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { float: left; width: 50%; } @@ -22,12 +26,12 @@ } .controls { - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { display: -webkit-flex; display: flex; } - .dropdown-menu.dropdown-menu-align-right { + .dropdown-menu.dropdown-menu-right { margin-top: -2px; } } @@ -35,7 +39,7 @@ .form-horizontal { margin-top: 20px; - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { display: -webkit-flex; display: flex; margin-top: 3px; @@ -45,20 +49,20 @@ .btn-remove { width: 100%; - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { width: auto; } } &.existing-title { - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { float: left; } } } .member-form-control { - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { padding-bottom: 5px; margin-left: 0; margin-right: 0; @@ -73,7 +77,7 @@ .member-search-form { position: relative; - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { float: right; } @@ -86,7 +90,7 @@ width: 100%; } - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { margin-top: 0; width: 155px; } @@ -96,19 +100,9 @@ width: 100%; padding-right: 35px; - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { width: 250px; } - - &.input-short { - @media (min-width: $screen-md-min) { - width: 170px; - } - - @media (min-width: $screen-lg-min) { - width: 210px; - } - } } } @@ -124,7 +118,7 @@ border: 0; outline: 0; - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { right: 160px; } } @@ -135,7 +129,7 @@ align-items: center; justify-content: center; - @media (max-width: $screen-sm-min) { + @include media-breakpoint-down(sm) { display: block; .flex-project-title { @@ -151,7 +145,7 @@ text-overflow: ellipsis; } - .badge { + .badge.badge-pill { height: 17px; line-height: 16px; margin-right: 5px; @@ -166,14 +160,14 @@ } } -.panel { - .panel-heading { - .badge { +.card { + .card-header { + .badge.badge-pill { margin-top: 0; } - @media (max-width: $screen-sm-min) { - .badge { + @include media-breakpoint-down(sm) { + .badge.badge-pill { margin-right: 0; margin-left: 0; } @@ -217,7 +211,7 @@ margin-right: 0; } - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { display: block; .controls > .btn { @@ -245,7 +239,7 @@ } } -.panel-mobile { +.card-mobile { .content-list.members-list li { display: block; diff --git a/app/assets/stylesheets/pages/merge_conflicts.scss b/app/assets/stylesheets/pages/merge_conflicts.scss index 04bde64c752..e76525fdbf6 100644 --- a/app/assets/stylesheets/pages/merge_conflicts.scss +++ b/app/assets/stylesheets/pages/merge_conflicts.scss @@ -286,6 +286,14 @@ $colors: ( } .resolve-conflicts-form { - padding-top: $gl-padding; + h4 { + margin-top: 0; + } + + .resolve-info { + @media(max-width: map-get($grid-breakpoints, lg)-1) { + margin-bottom: $gl-padding; + } + } } } diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss index 3581dd36a10..9eceb3e9a33 100644 --- a/app/assets/stylesheets/pages/merge_requests.scss +++ b/app/assets/stylesheets/pages/merge_requests.scss @@ -131,7 +131,7 @@ color: $gl-text-color; display: flex; - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { flex-wrap: wrap; } } @@ -282,7 +282,7 @@ display: inline-block; } - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { p { font-size: 13px; } @@ -494,18 +494,18 @@ } } -.panel-new-merge-request { - .panel-heading { +.card-new-merge-request { + .card-header { padding: 5px 10px; font-weight: $gl-font-weight-bold; line-height: 25px; } - .panel-body { + .card-body { padding: 10px 5px; } - .panel-footer { + .card-footer { padding: 0; .btn { @@ -519,7 +519,7 @@ } .item-title { - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { width: 45%; } } @@ -550,7 +550,7 @@ margin-bottom: 0; } - @media (min-width: $screen-xs-min) { + @include media-breakpoint-up(xs) { float: left; width: 50%; margin-bottom: 0; @@ -648,7 +648,7 @@ background-color: $white-light; border-bottom: 1px solid $border-color; - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { position: sticky; position: -webkit-sticky; } @@ -657,7 +657,7 @@ left: 0; transition: right .15s; - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { right: 0; } @@ -700,7 +700,7 @@ display: flex; justify-content: space-between; - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { flex-direction: column-reverse; } } @@ -736,7 +736,7 @@ display: flex; flex-wrap: wrap; - @media (min-width: $screen-xs) { + @include media-breakpoint-up(xs) { flex-wrap: nowrap; white-space: nowrap; } @@ -753,7 +753,7 @@ min-width: 100px; max-width: 150px; - @media (min-width: $screen-xs) { + @include media-breakpoint-up(xs) { min-width: 0; max-width: 100%; } diff --git a/app/assets/stylesheets/pages/milestone.scss b/app/assets/stylesheets/pages/milestone.scss index bac3b70c734..dba83e56d72 100644 --- a/app/assets/stylesheets/pages/milestone.scss +++ b/app/assets/stylesheets/pages/milestone.scss @@ -31,7 +31,7 @@ } } - .panel-heading { + .card-header { line-height: $line-height-base; padding: 14px 16px; display: -webkit-flex; @@ -145,7 +145,7 @@ padding: 20px 0; } -@media (max-width: $screen-xs-max) { +@include media-breakpoint-down(xs) { .milestone-actions { @include clearfix(); padding-top: $gl-vert-padding; @@ -181,7 +181,7 @@ width: 100%; } - @media (min-width: $screen-xs-min) { + @include media-breakpoint-up(xs) { .milestone-buttons .verbose { display: inline; } @@ -229,7 +229,7 @@ } } -@media (max-width: $screen-xs-max) { +@include media-breakpoint-down(xs) { .milestone-banner-text, .milestone-banner-link { display: inline; diff --git a/app/assets/stylesheets/pages/note_form.scss b/app/assets/stylesheets/pages/note_form.scss index 4a528bc2bb1..3b037d066dc 100644 --- a/app/assets/stylesheets/pages/note_form.scss +++ b/app/assets/stylesheets/pages/note_form.scss @@ -51,7 +51,7 @@ } .note-image-attach { - @extend .col-md-4; + @extend .col-lg-4; margin-left: 45px; float: none; } @@ -93,7 +93,7 @@ -webkit-flex-flow: row wrap; width: 100%; - .pull-right { + .float-right { // Flexbox quirk to make sure right-aligned items stay right-aligned. margin-left: auto; } @@ -185,12 +185,12 @@ } .notes.notes-form > li.timeline-entry { - @include notes-media('max', $screen-sm-max) { + @include notes-media('max', map-get($grid-breakpoints, md) - 1) { padding: 0; } .timeline-content { - @include notes-media('max', $screen-sm-max) { + @include notes-media('max', map-get($grid-breakpoints, md) - 1) { margin: 0; } } @@ -326,7 +326,7 @@ outline: 0; } - @media (min-width: $screen-md-min) { + @include media-breakpoint-up(md) { float: left; margin-right: $gl-padding; @@ -350,13 +350,13 @@ line-height: 16px; margin-top: 2px; - @media (min-width: $screen-md-min) { + @include media-breakpoint-up(md) { float: left; } } .note-form-actions { - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { .btn { float: none; width: 100%; @@ -375,7 +375,7 @@ left: 127px; top: 2px; - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { position: relative; top: 0; left: 0; @@ -410,7 +410,7 @@ width: 298px; } - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { display: flex; width: 100%; margin-bottom: 10px; @@ -432,7 +432,7 @@ .uploading-container { float: right; - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { float: left; margin-top: 5px; } @@ -444,7 +444,7 @@ } .uploading-error-message { - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { &::after { content: "\a"; white-space: pre; diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss index 6d5c6cb136f..299eda53140 100644 --- a/app/assets/stylesheets/pages/notes.scss +++ b/app/assets/stylesheets/pages/notes.scss @@ -22,7 +22,7 @@ ul.notes { .discussion-body { padding-top: 8px; - .panel { + .card { margin-bottom: 0; } } @@ -42,7 +42,7 @@ ul.notes { position: relative; border-bottom: 0; - @include notes-media('min', $screen-sm-min) { + @include notes-media('min', map-get($grid-breakpoints, sm)) { padding-left: $note-icon-gutter-width; } @@ -66,7 +66,7 @@ ul.notes { } .timeline-icon { - @include notes-media('min', $screen-sm-min) { + @include notes-media('min', map-get($grid-breakpoints, sm)) { margin-left: -$note-icon-gutter-width; } } @@ -74,7 +74,7 @@ ul.notes { .timeline-content { margin-left: $note-icon-gutter-width; - @include notes-media('min', $screen-sm-min) { + @include notes-media('min', map-get($grid-breakpoints, sm)) { margin-left: 0; } } @@ -154,7 +154,7 @@ ul.notes { .note-header { - @include notes-media('max', $screen-xs-min) { + @include notes-media('max', map-get($grid-breakpoints, xs)) { .inline { display: block; } @@ -217,7 +217,7 @@ ul.notes { .timeline-icon { float: left; - @include notes-media('min', $screen-sm-min) { + @include notes-media('min', map-get($grid-breakpoints, sm)) { margin-left: 0; width: auto; } @@ -231,7 +231,7 @@ ul.notes { } .timeline-content { - @include notes-media('min', $screen-sm-min) { + @include notes-media('min', map-get($grid-breakpoints, sm)) { margin-left: 30px; } } @@ -407,10 +407,6 @@ ul.notes { .note-header { display: flex; justify-content: space-between; - - @include notes-media('max', $screen-xs-max) { - flex-flow: row wrap; - } } .note-header-info { @@ -427,7 +423,7 @@ ul.notes { } .note-header-author-name { - @include notes-media('max', $screen-xs-max) { + @include notes-media('max', map-get($grid-breakpoints, sm) - 1) { display: none; } } @@ -435,7 +431,7 @@ ul.notes { .note-headline-light { display: inline; - @include notes-media('max', $screen-xs-min) { + @include notes-media('max', map-get($grid-breakpoints, xs)) { display: block; } } @@ -459,6 +455,10 @@ ul.notes { white-space: normal; } + .system-note-separator { + color: $gl-text-color-disabled; + } + a:hover { text-decoration: underline; } @@ -473,11 +473,6 @@ ul.notes { margin-left: 10px; color: $gray-darkest; - @include notes-media('max', $screen-md-max) { - float: none; - margin-left: 0; - } - .btn-group > .discussion-next-btn { margin-left: -1px; } @@ -491,7 +486,7 @@ ul.notes { margin-left: 10px; color: $gray-darkest; - @include notes-media('max', $screen-xs-max) { + @include notes-media('max', map-get($grid-breakpoints, sm) - 1) { float: none; margin-left: 0; } @@ -639,6 +634,10 @@ ul.notes { margin-left: -55px; position: absolute; z-index: 10; + + .new & { + margin-top: -10px; + } } .discussion-body, @@ -673,7 +672,7 @@ ul.notes { } .line-resolve-all-container { - @include notes-media('min', $screen-sm-min) { + @include notes-media('min', map-get($grid-breakpoints, sm)) { margin-right: 0; padding-left: $gl-padding; } diff --git a/app/assets/stylesheets/pages/notifications.scss b/app/assets/stylesheets/pages/notifications.scss index bdf07a99daf..e98cb444f0a 100644 --- a/app/assets/stylesheets/pages/notifications.scss +++ b/app/assets/stylesheets/pages/notifications.scss @@ -2,7 +2,7 @@ line-height: 34px; .dropdown-menu { - @extend .dropdown-menu-align-right; + @extend .dropdown-menu-right; } } diff --git a/app/assets/stylesheets/pages/pipeline_schedules.scss b/app/assets/stylesheets/pages/pipeline_schedules.scss index bc7fa8a26d9..86e70955389 100644 --- a/app/assets/stylesheets/pages/pipeline_schedules.scss +++ b/app/assets/stylesheets/pages/pipeline_schedules.scss @@ -69,7 +69,7 @@ .cron-preset-radio-input { display: inline-block; - @media (max-width: $screen-md-max) { + @include media-breakpoint-down(md) { display: block; margin: 0 0 5px 5px; } diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index 02803e7b040..0188a55cbf3 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -16,13 +16,13 @@ margin: 0; white-space: normal; - @media (max-width: $screen-sm-max) { + @include media-breakpoint-down(sm) { justify-content: flex-end; } } .ci-table { - .label { + .badge { margin-bottom: 3px; } @@ -66,13 +66,9 @@ } } - .btn-group { - &.open { - .btn-default { - background-color: $white-normal; - border-color: $border-white-normal; - } - } + .btn-group.open .btn-default { + background-color: $white-normal; + border-color: $border-white-normal; } .btn .text-center { @@ -86,7 +82,7 @@ } } -@media (max-width: $screen-md-max) { +@include media-breakpoint-down(md) { .content-list { &.builds-content-list { width: 100%; @@ -154,14 +150,14 @@ color: $gl-link-color; } - .label { + .badge { margin-right: 4px; } .label-container { font-size: 0; - .label { + .badge { margin-top: 5px; } } @@ -230,7 +226,7 @@ .stage-cell { &.table-section { - @media (min-width: $screen-md-min) { + @include media-breakpoint-up(md) { min-width: 160px; /* Hack alert: Without this the mini graph pipeline won't work properly*/ margin-right: -4px; } @@ -361,16 +357,14 @@ &:not(:first-child) { margin-left: 44px; - .left-connector { - &::before { - content: ''; - position: absolute; - top: 48%; - left: -44px; - border-top: 2px solid $border-color; - width: 44px; - height: 1px; - } + .left-connector::before { + content: ''; + position: absolute; + top: 48%; + left: -44px; + border-top: 2px solid $border-color; + width: 44px; + height: 1px; } } } @@ -386,22 +380,16 @@ &:last-child { .build { // Remove right connecting horizontal line from first build in last stage - &:first-child { - &::after { - border: 0; - } + &:first-child::after { + border: 0; } // Remove right curved connectors from all builds in last stage - &:not(:first-child) { - &::after { - border: 0; - } + &:not(:first-child)::after { + border: 0; } // Remove opposite curve - .curve { - &::before { - display: none; - } + .curve::before { + display: none; } } } @@ -409,16 +397,12 @@ &:first-child { .build { // Remove left curved connectors from all builds in first stage - &:not(:first-child) { - &::before { - border: 0; - } + &:not(:first-child)::before { + border: 0; } // Remove opposite curve - .curve { - &::after { - display: none; - } + .curve::after { + display: none; } } } @@ -816,7 +800,7 @@ button.mini-pipeline-graph-dropdown-toggle { display: block; } - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { max-width: 60%; } } @@ -903,7 +887,7 @@ button.mini-pipeline-graph-dropdown-toggle { transform: translate(-50%, 0); border-width: 0 5px 6px; - @media (max-width: $screen-sm-max) { + @include media-breakpoint-down(sm) { left: 100%; margin-left: -12px; } @@ -925,7 +909,7 @@ button.mini-pipeline-graph-dropdown-toggle { &.dropdown-menu { transform: translate(-80%, 0); - @media (min-width: $screen-md-min) { + @media(min-width: map-get($grid-breakpoints, md)) { transform: translate(-50%, 0); right: auto; left: 50%; diff --git a/app/assets/stylesheets/pages/profile.scss b/app/assets/stylesheets/pages/profile.scss index b199f9876d3..06078f1d12e 100644 --- a/app/assets/stylesheets/pages/profile.scss +++ b/app/assets/stylesheets/pages/profile.scss @@ -5,7 +5,7 @@ } .avatar-image { - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { float: left; margin-bottom: 0; } @@ -119,7 +119,7 @@ .key-list-item { .key-list-item-info { - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { float: left; } } @@ -188,7 +188,7 @@ .modal-dialog { width: 380px; - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { width: auto; } @@ -242,7 +242,7 @@ left: 0; } - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { .cover-block { padding-top: 20px; } @@ -352,7 +352,7 @@ table.u2f-registrations { } } - @media(max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { text-align: center; .bordered-box { @@ -414,7 +414,7 @@ table.u2f-registrations { } &.unverified { - @include status-color($gray-dark, $gray, $common-gray-dark); + @include status-color($gray-dark, color("gray"), $common-gray-dark); } } } diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index dd0cb2c2613..22964163e95 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -9,7 +9,7 @@ .new_project, .edit-project, .import-project { - .help-block { + .form-text.text-muted { margin-bottom: 10px; } @@ -34,7 +34,7 @@ } } - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { .input-group > div { &:last-child { margin-bottom: 0; @@ -46,7 +46,8 @@ } } - .input-group-addon { + .input-group-prepend, + .input-group-append { overflow: hidden; text-overflow: ellipsis; line-height: unset; @@ -82,7 +83,7 @@ border: 1px solid $border-color; padding: 10px 32px; - @media (max-width: $screen-xs-min) { + @include media-breakpoint-down(xs) { padding: 10px 20px; } } @@ -134,7 +135,7 @@ max-width: 400px; } - @media (max-width: $screen-xs-min) { + @include media-breakpoint-down(xs) { padding-left: 20px; } } @@ -144,7 +145,7 @@ padding-top: 24px; padding-bottom: 24px; - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { border-bottom: 1px solid $border-color; } @@ -230,11 +231,11 @@ } .notification-dropdown .dropdown-menu { - @extend .dropdown-menu-align-right; + @extend .dropdown-menu-right; } .download-button { - @media (max-width: $screen-md-max) { + @include media-breakpoint-down(md) { margin-left: 0; } } @@ -444,11 +445,11 @@ height: 200px; width: calc((100% / 2) - #{$gl-padding * 2}); - @media (min-width: $screen-md-min) { + @include media-breakpoint-up(md) { width: calc((100% / 4) - #{$gl-padding * 2}); } - @media (min-width: $screen-lg-min) { + @include media-breakpoint-up(lg) { width: calc((100% / 5) - #{$gl-padding * 2}); } @@ -537,11 +538,12 @@ .template-input-group { position: relative; - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { display: flex; } - .input-group-addon { + .input-group-prepend, + .input-group-append { flex: 1; text-align: left; padding-left: ($gl-padding * 3); @@ -601,12 +603,12 @@ margin: 0 auto 4px; font-size: 24px; - @media (min-width: $screen-xs-max) { + @media (min-width: map-get($grid-breakpoints, sm)-1) { top: 0; } } - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { .btn-template-icon { display: inline-block; height: 14px; @@ -625,31 +627,31 @@ .create-project-options { display: flex; - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { display: block; } .first-column { - @media (min-width: $screen-xs-min) { + @include media-breakpoint-up(xs) { max-width: 50%; padding-right: 30px; } - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { max-width: 100%; width: 100%; } } .second-column { - @media (min-width: $screen-xs-min) { + @include media-breakpoint-up(xs) { width: 50%; flex: 1; padding-left: 30px; position: relative; } - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { max-width: 100%; width: 100%; padding-left: 0; @@ -657,7 +659,7 @@ } // Mobile - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { padding-top: 30px; } @@ -677,7 +679,7 @@ line-height: 20px; // Mobile - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { left: 50%; top: 0; transform: translateX(-50%); @@ -697,7 +699,7 @@ top: 0; // Mobile - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { top: 10px; left: 10px; right: 10px; @@ -735,7 +737,7 @@ vertical-align: top; margin-top: 0; - @media (min-width: $screen-lg-min) { + @include media-breakpoint-up(lg) { float: right; } } @@ -866,19 +868,14 @@ pre.light-well { } } -.panel .projects-list li { +.card .projects-list li { padding: 10px 15px; margin: 0; } -.commits-search-form { - .input-short { - min-width: 200px; - } -} - .git-clone-holder { width: 380px; + height: 28px; .btn-clipboard { border: 1px solid $border-color; @@ -894,11 +891,11 @@ pre.light-well { .form-control { @extend .monospace; - background: $white-light; + background-color: $white-light; + border-color: $border-color; font-size: 14px; margin-left: -1px; cursor: auto; - width: 101%; } } @@ -927,7 +924,8 @@ pre.light-well { } .project-tip-command { - > .input-group-btn:first-child { + > .input-group-prepend:first-child, + > .input-group-append:first-child { width: auto; } } @@ -978,7 +976,7 @@ pre.light-well { .dropdown-menu-projects { width: 300px; - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { width: 500px; } @@ -992,7 +990,7 @@ pre.light-well { .inline-input-group { width: 100%; - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { width: 300px; } } @@ -1003,8 +1001,8 @@ pre.light-well { text-align: center; margin-top: -20px; - @media (min-width: $screen-sm-min) { - margin-top: 0; + @include media-breakpoint-up(sm) { + margin: 0 $gl-padding-8; width: auto; } } @@ -1042,7 +1040,7 @@ pre.light-well { } &.form-group { - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { margin-bottom: 0; } } @@ -1070,12 +1068,12 @@ pre.light-well { .project-feature { padding-top: 10px; - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { padding-left: 45px; } &.nested { - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { padding-left: 90px; } } diff --git a/app/assets/stylesheets/pages/repo.scss b/app/assets/stylesheets/pages/repo.scss index 00457717f00..17d7087bd85 100644 --- a/app/assets/stylesheets/pages/repo.scss +++ b/app/assets/stylesheets/pages/repo.scss @@ -22,7 +22,6 @@ height: calc(100vh - #{$header-height}); margin-top: 0; border-top: 1px solid $white-dark; - border-bottom: 1px solid $white-dark; padding-bottom: $ide-statusbar-height; &.is-collapsed { @@ -39,12 +38,15 @@ .ide-file-list { flex: 1; + padding-left: $gl-padding; + padding-right: $gl-padding; + padding-bottom: $grid-size; .file { cursor: pointer; &.file-open { - background: $link-active-background; + background: $white-normal; } &.file-active { @@ -84,12 +86,11 @@ .ide-new-btn { display: none; - margin-right: -8px; } &:hover, &:focus { - background: $link-active-background; + background: $white-normal; .ide-new-btn { display: block; @@ -111,12 +112,11 @@ } } -.file-name, -.file-col-commit-message { +.file-name { display: flex; overflow: visible; align-items: center; - padding: 6px 12px; + width: 100%; } .multi-file-loading-container { @@ -306,8 +306,18 @@ } .preview-container { - height: 100%; - overflow: auto; + flex-grow: 1; + position: relative; + + .md-previewer { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + overflow: auto; + padding: $gl-padding; + } .file-container { background-color: $gray-darker; @@ -347,10 +357,6 @@ color: $diff-image-info-color; } } - - .md-previewer { - padding: $gl-padding; - } } .ide-mode-tabs { @@ -373,7 +379,7 @@ .ide-status-bar { border-top: 1px solid $white-dark; - padding: $gl-bar-padding $gl-padding; + padding: 2px $gl-padding-8 0; background: $white-light; display: flex; justify-content: space-between; @@ -384,12 +390,19 @@ left: 0; width: 100%; + font-size: 12px; + line-height: 22px; + + * { + font-size: inherit; + } + > div + div { padding-left: $gl-padding; } svg { - vertical-align: middle; + vertical-align: sub; } } @@ -501,7 +514,7 @@ align-items: center; margin-bottom: 0; border-bottom: 1px solid $white-dark; - padding: $gl-btn-padding $gl-padding; + padding: 12px 0; } .multi-file-commit-panel-header-title { @@ -523,32 +536,31 @@ .multi-file-commit-list { flex: 1; overflow: auto; - padding: $gl-padding; + padding: $grid-size 0; + margin-left: -$grid-size; + margin-right: -$grid-size; min-height: 60px; + + .multi-file-commit-list-item { + margin-left: 0; + margin-right: 0; + } + + &.help-block { + margin-left: 0; + right: 0; + } } .multi-file-commit-list-item { - display: flex; - padding: 0; - align-items: center; - border-radius: $border-radius-default; - .multi-file-discard-btn { display: none; margin-top: -2px; margin-left: auto; - margin-right: $grid-size; color: $gl-link-color; - - &:focus, - &:hover { - text-decoration: underline; - } } &:hover { - background: $white-normal; - .multi-file-discard-btn { display: flex; } @@ -584,25 +596,39 @@ } } +.multi-file-commit-list-item, +.ide-file-list .file { + display: flex; + align-items: center; + margin-left: -$grid-size; + margin-right: -$grid-size; + padding: $grid-size / 2 $grid-size; + border-radius: $border-radius-default; + text-align: left; + + &:hover, + &:focus { + background: $white-normal; + } +} + .multi-file-commit-list-path { - padding: $grid-size / 2; - padding-left: $grid-size; + padding: 0; background: none; border: 0; text-align: left; width: 100%; - min-width: 0; + + &:hover, + &:focus { + outline: 0; + } svg { min-width: 16px; vertical-align: middle; display: inline-block; } - - &:hover, - &:focus { - outline: 0; - } } .multi-file-commit-list-file-path { @@ -619,12 +645,18 @@ .multi-file-commit-form { position: relative; - padding: $gl-padding; background-color: $white-light; - border-top: 1px solid $white-dark; border-left: 1px solid $white-dark; transition: all 0.3s ease; + > form, + > .commit-form-compact { + padding: $gl-padding 0; + margin-left: $gl-padding; + margin-right: $gl-padding; + border-top: 1px solid $white-dark; + } + .btn { font-size: $gl-font-size; } @@ -787,8 +819,9 @@ display: flex; flex: 1; flex-direction: column; - width: 100%; min-height: 140px; + margin-left: $gl-padding; + margin-right: $gl-padding; &.is-first { border-bottom: 1px solid $white-dark; @@ -821,7 +854,7 @@ } } - .help-block { + .form-text.text-muted { margin-top: 0; line-height: 0; } @@ -979,9 +1012,8 @@ .ide-tree-header { display: flex; align-items: center; - padding: 10px 0; - margin-left: 10px; - margin-right: 10px; + margin-bottom: 8px; + padding: 12px 0; border-bottom: 1px solid $white-dark; .ide-new-btn { @@ -1012,9 +1044,9 @@ .commit-form-slide-up-enter-active, .commit-form-slide-up-leave-active { position: absolute; - top: 16px; - left: 16px; - right: 16px; + top: 0; + left: 0; + right: 0; transition: all 0.3s ease; } diff --git a/app/assets/stylesheets/pages/runners.scss b/app/assets/stylesheets/pages/runners.scss index 5fb97b13470..2734faec558 100644 --- a/app/assets/stylesheets/pages/runners.scss +++ b/app/assets/stylesheets/pages/runners.scss @@ -51,7 +51,7 @@ } } -@media (max-width: $screen-md-max) { +@include media-breakpoint-down(md) { .runners-content { width: 100%; overflow: auto; diff --git a/app/assets/stylesheets/pages/search.scss b/app/assets/stylesheets/pages/search.scss index dbde0720993..a35c4ff7c80 100644 --- a/app/assets/stylesheets/pages/search.scss +++ b/app/assets/stylesheets/pages/search.scss @@ -47,6 +47,7 @@ input[type="checkbox"]:hover { } .location-badge { + white-space: nowrap; height: 32px; font-size: 12px; margin: -4px 4px -4px -4px; @@ -166,7 +167,7 @@ input[type="checkbox"]:hover { } .search-holder { - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { display: -webkit-flex; display: flex; } @@ -178,7 +179,7 @@ input[type="checkbox"]:hover { position: relative; margin-right: 0; - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { margin-right: 5px; } } @@ -202,7 +203,7 @@ input[type="checkbox"]:hover { width: 100%; margin-top: 5px; - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { width: auto; margin-top: 0; margin-left: 5px; @@ -210,7 +211,7 @@ input[type="checkbox"]:hover { } .dropdown { - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { margin-left: 5px; margin-right: 5px; } @@ -220,7 +221,7 @@ input[type="checkbox"]:hover { width: 100%; margin-top: 5px; - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { width: 180px; margin-top: 0; } diff --git a/app/assets/stylesheets/pages/settings.scss b/app/assets/stylesheets/pages/settings.scss index c410049bc0b..2b3773eebad 100644 --- a/app/assets/stylesheets/pages/settings.scss +++ b/app/assets/stylesheets/pages/settings.scss @@ -70,7 +70,7 @@ animation: none; } - @media(max-width: $screen-sm-max) { + @media(max-width: map-get($grid-breakpoints, md)-1) { padding-right: 20px; } @@ -98,8 +98,8 @@ } .bs-callout, - .checkbox:first-child, - .help-block { + .form-check:first-child, + .form-text.text-muted { margin-top: 0; } @@ -131,12 +131,12 @@ color: $gl-danger; } -.service-settings .control-label { +.service-settings .form-control-label { padding-top: 0; } .integration-settings-form { - .well { + .card.card-body { padding: $gl-padding / 2; box-shadow: none; } @@ -158,7 +158,7 @@ } .visibility-level-setting { - .radio { + .form-check { margin-bottom: 10px; i.fa { @@ -174,7 +174,7 @@ .option-description, .option-disabled-reason { - margin-left: 29px; + margin-left: 45px; color: $project-option-descr-color; } @@ -199,22 +199,22 @@ } .prometheus-metrics-monitoring { - .panel { - .panel-toggle { + .card { + .card-toggle { width: 14px; } - .badge { + .badge.badge-pill { font-size: 12px; line-height: 12px; } - .panel-heading .badge-count { + .card-header .label-count { color: $white-light; background: $common-gray-dark; } - .panel-body { + .card-body { padding: 0; } @@ -249,7 +249,7 @@ li { padding: $gl-padding; - .badge { + .badge.badge-pill { margin-left: 5px; background: $badge-bg; } diff --git a/app/assets/stylesheets/pages/stat_graph.scss b/app/assets/stylesheets/pages/stat_graph.scss index 8e2c42c1bd3..3f6f5f06075 100644 --- a/app/assets/stylesheets/pages/stat_graph.scss +++ b/app/assets/stylesheets/pages/stat_graph.scss @@ -14,7 +14,10 @@ } #contributors-master { - @include make-md-column(12); + @include media-breakpoint-up(md) { + @include make-col-ready(); + @include make-col(12); + } svg { width: 100%; @@ -33,10 +36,14 @@ } .person { - @include make-md-column(6); + @include media-breakpoint-up(md) { + @include make-col-ready(); + @include make-col(6); + } + margin-top: 10px; - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { width: 100%; } diff --git a/app/assets/stylesheets/pages/status.scss b/app/assets/stylesheets/pages/status.scss index ade5ddd147b..620297e589d 100644 --- a/app/assets/stylesheets/pages/status.scss +++ b/app/assets/stylesheets/pages/status.scss @@ -58,7 +58,7 @@ } } -.visible-xs-inline { +.d-block.d-sm-none-inline { .ci-status-link { position: relative; top: 2px; diff --git a/app/assets/stylesheets/pages/todos.scss b/app/assets/stylesheets/pages/todos.scss index 4b9824fab0c..e5d7dd13915 100644 --- a/app/assets/stylesheets/pages/todos.scss +++ b/app/assets/stylesheets/pages/todos.scss @@ -126,7 +126,7 @@ color: $gl-grayish-blue; font-size: $gl-font-size; - .label { + .badge.badge-pill { color: $gl-text-color; } @@ -162,7 +162,7 @@ } } -@media (max-width: $screen-sm-max) { +@include media-breakpoint-down(sm) { .todos-filters { .dropdown-menu-toggle { width: 130px; @@ -174,7 +174,7 @@ } } -@media (max-width: $screen-xs-max) { +@include media-breakpoint-down(xs) { .todo { .avatar { display: none; @@ -214,7 +214,7 @@ margin-left: auto; margin-right: auto; - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { -webkit-flex-direction: row; flex-direction: row; padding-top: 80px; @@ -233,7 +233,7 @@ margin-left: auto; margin-right: auto; - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { width: 300px; margin-right: 0; -webkit-order: 2; @@ -244,7 +244,7 @@ .todos-all-done { padding-top: 20px; - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { padding-top: 50px; } diff --git a/app/assets/stylesheets/pages/tree.scss b/app/assets/stylesheets/pages/tree.scss index e0ee7e9aa3d..efd26cb1f81 100644 --- a/app/assets/stylesheets/pages/tree.scss +++ b/app/assets/stylesheets/pages/tree.scss @@ -7,7 +7,7 @@ color: $gl-text-color-secondary; } - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { display: flex; .tree-ref-container { @@ -41,15 +41,10 @@ position: relative; } } - - .add-to-tree-dropdown { - position: absolute; - left: 18px; - } } } - @media (max-width: $screen-xs-max) { + @include media-breakpoint-down(xs) { .repo-breadcrumb { margin-top: 10px; position: relative; @@ -121,7 +116,7 @@ margin-left: 5px; } - @media (min-width: $screen-md-min) and (max-width: $screen-md-max) { + @include media-breakpoint-only(md) { @include str-truncated(450px); } diff --git a/app/assets/stylesheets/pages/wiki.scss b/app/assets/stylesheets/pages/wiki.scss index e70a57c2a67..800f5c68e39 100644 --- a/app/assets/stylesheets/pages/wiki.scss +++ b/app/assets/stylesheets/pages/wiki.scss @@ -65,7 +65,7 @@ display: block; } - @media (min-width: $screen-sm-min) { + @include media-breakpoint-up(sm) { &.has-sidebar-toggle { padding-right: 40px; } @@ -81,7 +81,7 @@ } } - @media (min-width: $screen-md-min) { + @include media-breakpoint-up(md) { &.has-sidebar-toggle { padding-right: 0; } |