Commit fd18be78 authored by GitLab Bot's avatar GitLab Bot

Merge remote-tracking branch 'upstream/master' into ce-to-ee-2017-12-23

# Conflicts:
#	app/assets/images/icons.json
#	app/assets/images/icons.svg
#	app/assets/javascripts/ide/components/repo_file.vue
#	app/assets/javascripts/ide/lib/editor_options.js
#	app/assets/javascripts/monitoring/utils/date_time_formatters.js
#	app/assets/stylesheets/pages/merge_requests.scss
#	app/controllers/autocomplete_controller.rb
#	app/models/user.rb
#	app/services/search/global_service.rb
#	app/views/projects/tree/_tree_content.html.haml
#	app/views/projects/tree/_tree_header.html.haml
#	app/views/projects/tree/show.html.haml
#	app/workers/repository_import_worker.rb
#	doc/administration/auth/how_to_configure_ldap_gitlab_ce/index.md
#	doc/administration/auth/ldap.md
#	doc/ci/examples/browser_performance.md
#	doc/topics/authentication/index.md
#	doc/user/group/index.md
#	doc/workflow/rebase_before_merge.md
#	package.json
#	yarn.lock

[ci skip]
parents 9132cf51 46be07d2
10.3.0-pre
10.4.0-pre
<<<<<<< HEAD
{"iconCount":186,"spriteSize":84748,"icons":["abuse","account","admin","angle-double-left","angle-double-right","angle-down","angle-left","angle-right","angle-up","appearance","applications","approval","arrow-down","arrow-right","assignee","bold","book","bookmark","branch","bullhorn","calendar","cancel","chart","chevron-down","chevron-left","chevron-right","chevron-up","clock","close","code","collapse","comment-dots","comment-next","comment","comments","commit","credit-card","cut","dashboard","disk","doc_code","doc_image","doc_text","double-headed-arrow","download","duplicate","earth","ellipsis_v","emoji_slightly_smiling_face","emoji_smile","emoji_smiley","epic","external-link","eye-slash","eye","file-addition","file-deletion","file-modified","filter","folder-o","folder-open","folder","fork","geo-nodes","git-merge","group","history","home","hook","hourglass","image-comment-dark","image-comment-light","import","issue-block","issue-child","issue-close","issue-duplicate","issue-external","issue-new","issue-open-m","issue-open","issue-parent","issues","italic","key-2","key","label","labels","leave","level-up","license","link","list-bulleted","list-numbered","location-dot","location","lock-open","lock","log","mail","menu","merge-request-close","messages","mobile-issue-close","monitor","more","notifications-off","notifications","overview","pencil-square","pencil","pipeline","play","plus-square-o","plus-square","plus","podcast","preferences","profile","project","push-rules","question-o","question","quote","redo","remove","repeat","retry","scale","screen-full","screen-normal","scroll_down","scroll_up","search","settings","shield","slight-frown","slight-smile","smile","smiley","snippet","spam","spinner","star-o","star","status_canceled_borderless","status_canceled","status_closed","status_created_borderless","status_created","status_failed_borderless","status_failed","status_manual_borderless","status_manual","status_notfound_borderless","status_open","status_pending_borderless","status_pending","status_running_borderless","status_running","status_skipped_borderless","status_skipped","status_success_borderless","status_success_solid","status_success","status_warning_borderless","status_warning","stop","task-done","template","terminal","thumb-down","thumb-up","thumbtack","timer","todo-add","todo-done","token","unapproval","unassignee","unlink","user","users","volume-up","warning","work"]}
=======
{"iconCount":186,"spriteSize":84748,"icons":["abuse","account","admin","angle-double-left","angle-double-right","angle-down","angle-left","angle-right","angle-up","appearance","applications","approval","arrow-down","arrow-right","assignee","bold","book","bookmark","branch","bullhorn","calendar","cancel","chart","chevron-down","chevron-left","chevron-right","chevron-up","clock","close","code","collapse","comment-dots","comment-next","comment","comments","commit","credit-card","cut","dashboard","disk","doc_code","doc_image","doc_text","double-headed-arrow","download","duplicate","earth","ellipsis_v","emoji_slightly_smiling_face","emoji_smile","emoji_smiley","epic","external-link","eye-slash","eye","file-addition","file-deletion","file-modified","filter","folder-o","folder-open","folder","fork","geo-nodes","git-merge","group","history","home","hook","hourglass","image-comment-dark","image-comment-light","import","issue-block","issue-child","issue-close","issue-duplicate","issue-external","issue-new","issue-open-m","issue-open","issue-parent","issues","italic","key-2","key","label","labels","leave","level-up","license","link","list-bulleted","list-numbered","location-dot","location","lock-open","lock","log","mail","menu","merge-request-close","messages","mobile-issue-close","monitor","more","notifications-off","notifications","overview","pencil-square","pencil","pipeline","play","plus-square-o","plus-square","plus","podcast","preferences","profile","project","push-rules","question-o","question","quote","redo","remove","repeat","retry","scale","screen-full","screen-normal","scroll_down","scroll_up","search","settings","shield","slight-frown","slight-smile","smile","smiley","snippet","spam","spinner","star-o","star","status_canceled_borderless","status_canceled","status_closed","status_created_borderless","status_created","status_failed_borderless","status_failed","status_manual_borderless","status_manual","status_notfound_borderless","status_open","status_pending_borderless","status_pending","status_running_borderless","status_running","status_skipped_borderless","status_skipped","status_success_borderless","status_success_solid","status_success","status_warning_borderless","status_warning","stop","task-done","template","terminal","thumb-down","thumb-up","thumbtack","timer","todo-add","todo-done","token","unapproval","unassignee","unlink","user","users","volume-up","warning","work"]}
>>>>>>> upstream/master
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -30,6 +30,7 @@ export default class Clusters {
installHelmPath,
installIngressPath,
installRunnerPath,
installPrometheusPath,
clusterStatus,
clusterStatusReason,
helpPath,
......@@ -44,6 +45,7 @@ export default class Clusters {
installHelmEndpoint: installHelmPath,
installIngressEndpoint: installIngressPath,
installRunnerEndpoint: installRunnerPath,
installPrometheusEndpoint: installPrometheusPath,
});
this.toggle = this.toggle.bind(this);
......
......@@ -67,6 +67,16 @@ export default {
and send the results back to GitLab.`,
));
},
prometheusDescription() {
return sprintf(
_.escape(s__('ClusterIntegration|Prometheus is an open-source monitoring system with %{gitlabIntegrationLink} to monitor deployed applications.')), {
gitlabIntegrationLink: `<a href="https://docs.gitlab.com/ce/user/project/integrations/prometheus.html", target="_blank" rel="noopener noreferrer">
${_.escape(s__('ClusterIntegration|Gitlab Integration'))}
</a>`,
},
false,
);
},
},
};
</script>
......@@ -105,6 +115,16 @@ export default {
:status-reason="applications.ingress.statusReason"
:request-status="applications.ingress.requestStatus"
:request-reason="applications.ingress.requestReason"
/>
<application-row
id="prometheus"
:title="applications.prometheus.title"
title-link="https://prometheus.io/docs/introduction/overview/"
:description="prometheusDescription"
:status="applications.prometheus.status"
:status-reason="applications.prometheus.statusReason"
:request-status="applications.prometheus.requestStatus"
:request-reason="applications.prometheus.requestReason"
/>
<!-- NOTE: Don't forget to update `clusters.scss` min-height for this block and uncomment `application_spec` tests -->
<!-- Add GitLab Runner row, all other plumbing is complete -->
......
......@@ -7,6 +7,7 @@ export default class ClusterService {
helm: this.options.installHelmEndpoint,
ingress: this.options.installIngressEndpoint,
runner: this.options.installRunnerEndpoint,
prometheus: this.options.installPrometheusEndpoint,
};
}
......
......@@ -28,6 +28,13 @@ export default class ClusterStore {
requestStatus: null,
requestReason: null,
},
prometheus: {
title: s__('ClusterIntegration|Prometheus'),
status: null,
statusReason: null,
requestStatus: null,
requestReason: null,
},
},
};
}
......
......@@ -2,6 +2,7 @@
import userAvatarImage from '../../vue_shared/components/user_avatar/user_avatar_image.vue';
import limitWarning from './limit_warning_component.vue';
import totalTime from './total_time_component.vue';
import icon from '../../vue_shared/components/icon.vue';
export default {
props: {
......@@ -12,6 +13,7 @@
userAvatarImage,
totalTime,
limitWarning,
icon,
},
};
</script>
......@@ -52,7 +54,10 @@
</template>
<template v-else>
<span class="merge-request-branch" v-if="mergeRequest.branch">
<i class= "fa fa-code-fork"></i>
<icon
name="fork"
:size="16">
</icon>
<a :href="mergeRequest.branch.url">{{ mergeRequest.branch.name }}</a>
</span>
</template>
......
......@@ -3,6 +3,7 @@
import iconBranch from '../svg/icon_branch.svg';
import limitWarning from './limit_warning_component.vue';
import totalTime from './total_time_component.vue';
import icon from '../../vue_shared/components/icon.vue';
export default {
props: {
......@@ -13,6 +14,7 @@
userAvatarImage,
totalTime,
limitWarning,
icon,
},
computed: {
iconBranch() {
......@@ -37,7 +39,10 @@
<user-avatar-image :img-src="build.author.avatarUrl"/>
<h5 class="item-title">
<a :href="build.url" class="pipeline-id">#{{ build.id }}</a>
<i class="fa fa-code-fork"></i>
<icon
name="fork"
:size="16">
</icon>
<a :href="build.branch.url" class="ref-name">{{ build.branch.name }}</a>
<span class="icon-branch" v-html="iconBranch"></span>
<a :href="build.commitUrl" class="commit-sha">{{ build.shortSha }}</a>
......
......@@ -3,6 +3,7 @@
import iconBranch from '../svg/icon_branch.svg';
import limitWarning from './limit_warning_component.vue';
import totalTime from './total_time_component.vue';
import icon from '../../vue_shared/components/icon.vue';
export default {
props: {
......@@ -12,6 +13,7 @@
components: {
totalTime,
limitWarning,
icon,
},
computed: {
iconBuildStatus() {
......@@ -40,7 +42,10 @@
<a :href="build.url" class="item-build-name">{{ build.name }}</a>
&middot;
<a :href="build.url" class="pipeline-id">#{{ build.id }}</a>
<i class="fa fa-code-fork"></i>
<icon
name="fork"
:size="16">
</icon>
<a :href="build.branch.url" class="ref-name">{{ build.branch.name }}</a>
<span class="icon-branch" v-html="iconBranch"></span>
<a :href="build.commitUrl" class="commit-sha">{{ build.shortSha }}</a>
......
......@@ -123,6 +123,8 @@ import initLDAPGroupsSelect from 'ee/ldap_groups_select'; // eslint-disable-line
return false;
}
const fail = () => Flash('Error loading dynamic module');
path = page.split(':');
shortcut_handler = null;
......@@ -606,7 +608,7 @@ import initLDAPGroupsSelect from 'ee/ldap_groups_select'; // eslint-disable-line
new CILintEditor();
break;
case 'users:show':
new UserCallout();
import('./pages/users/show').then(m => m.default()).catch(fail);
break;
case 'admin:conversational_development_index:show':
new UserCallout();
......
......@@ -300,7 +300,7 @@ GitLabDropdown = (function() {
return function(data) {
_this.fullData = data;
_this.parseData(_this.fullData);
_this.focusTextInput(true);
_this.focusTextInput();
if (_this.options.filterable && _this.filter && _this.filter.input && _this.filter.input.val() && _this.filter.input.val().trim() !== '') {
return _this.filter.input.trigger('input');
}
......@@ -806,24 +806,16 @@ GitLabDropdown = (function() {
return [selectedObject, isMarking];
};
GitLabDropdown.prototype.focusTextInput = function(triggerFocus = false) {
GitLabDropdown.prototype.focusTextInput = function() {
if (this.options.filterable) {
this.dropdown.one('transitionend', () => {
const initialScrollTop = $(window).scrollTop();
const initialScrollTop = $(window).scrollTop();
if (this.dropdown.is('.open')) {
this.filterInput.focus();
}
if ($(window).scrollTop() < initialScrollTop) {
$(window).scrollTop(initialScrollTop);
}
});
if (this.dropdown.is('.open')) {
this.filterInput.focus();
}
if (triggerFocus) {
// This triggers after a ajax request
// in case of slow requests, the dropdown transition could already be finished
this.dropdown.trigger('transitionend');
if ($(window).scrollTop() < initialScrollTop) {
$(window).scrollTop(initialScrollTop);
}
}
};
......
......@@ -2,7 +2,10 @@
import { mapState } from 'vuex';
import timeAgoMixin from '../../vue_shared/mixins/timeago';
import skeletonLoadingContainer from '../../vue_shared/components/skeleton_loading_container.vue';
<<<<<<< HEAD:app/assets/javascripts/ide/components/repo_file.vue
import fileStatusIcon from './repo_file_status_icon.vue';
=======
>>>>>>> upstream/master:app/assets/javascripts/ide/components/repo_file.vue
import newDropdown from './new_dropdown/index.vue';
export default {
......@@ -12,7 +15,10 @@
components: {
skeletonLoadingContainer,
newDropdown,
<<<<<<< HEAD:app/assets/javascripts/ide/components/repo_file.vue
fileStatusIcon,
=======
>>>>>>> upstream/master:app/assets/javascripts/ide/components/repo_file.vue
},
props: {
file: {
......
export default [{
readOnly: model => !!model.file.file_lock,
}];
......@@ -2,7 +2,7 @@ import timeago from 'timeago.js';
import dateFormat from 'vendor/date.format';
import { pluralize } from './text_utility';
import {
lang,
languageCode,
s__,
} from '../../locale';
......@@ -24,7 +24,15 @@ export const getDayName = date => ['Sunday', 'Monday', 'Tuesday', 'Wednesday', '
*/
export const formatDate = datetime => dateFormat(datetime, 'mmm d, yyyy h:MMtt Z');
/**
* Timeago uses underscores instead of dashes to separate language from country code.
*
* see https://github.com/hustcc/timeago.js/tree/v3.0.0/locales
*/
const timeagoLanguageCode = languageCode().replace(/-/g, '_');
let timeagoInstance;
/**
* Sets a timeago Instance
*/
......@@ -67,8 +75,8 @@ export function getTimeago() {
][index];
};
timeago.register(lang, locale);
timeago.register(`${lang}-remaining`, localeRemaining);
timeago.register(timeagoLanguageCode, locale);
timeago.register(`${timeagoLanguageCode}-remaining`, localeRemaining);
timeagoInstance = timeago();
}
......@@ -83,7 +91,7 @@ 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
getTimeago().render(timeagoEls, lang);
getTimeago().render(timeagoEls, timeagoLanguageCode);
};
/**
......@@ -118,7 +126,7 @@ export const timeFor = (time, expiredLabel) => {
if (new Date(time) < new Date()) {
return expiredLabel || s__('Timeago|Past due');
}
return getTimeago().format(time, `${lang}-remaining`).trim();
return getTimeago().format(time, `${timeagoLanguageCode}-remaining`).trim();
};
export const getDayDifference = (a, b) => {
......
......@@ -4,9 +4,15 @@ import { bisector } from 'd3-array';
const d3 = { time, bisector, timeSecond, timeMinute, timeHour, timeDay, timeMonth, timeYear };
<<<<<<< HEAD
export const dateFormatWithName = d3.time('%a, %b %-d');
export const dateFormat = d3.time('%b %-d, %Y');
export const timeFormat = d3.time('%-I:%M%p');
=======
export const dateFormat = d3.time('%b %-d, %Y');
export const timeFormat = d3.time('%-I:%M%p');
export const dateFormatWithName = d3.time('%a, %b %-d');
>>>>>>> upstream/master
export const bisectDate = d3.bisector(d => d.time).left;
export function timeScaleFormat(date) {
......
import UserCallout from '~/user_callout';
export default () => new UserCallout();
<script>
import tooltip from '../../vue_shared/directives/tooltip';
import icon from '../../vue_shared/components/icon.vue';
export default {
props: {
......@@ -11,6 +12,9 @@
directives: {
tooltip,
},
components: {
icon,
},
};
</script>
<template>
......@@ -24,10 +28,9 @@
data-placement="top"
data-toggle="dropdown"
aria-label="Artifacts">
<i
class="fa fa-download"
aria-hidden="true">
</i>
<icon
name="download">
</icon>
<i
class="fa fa-caret-down"
aria-hidden="true">
......
......@@ -117,12 +117,10 @@
}());
markdownPreview = new window.MarkdownPreview();
previewButtonSelector = '.js-md-preview-button';
writeButtonSelector = '.js-md-write-button';
lastTextareaPreviewed = null;
const markdownToolbar = $('.md-header-toolbar');
$.fn.setupMarkdownPreview = function () {
var $form = $(this);
......@@ -146,6 +144,7 @@
// toggle content
$form.find('.md-write-holder').hide();
$form.find('.md-preview-holder').show();
markdownToolbar.removeClass('active');
markdownPreview.showPreview($form);
});
......@@ -167,6 +166,7 @@
$form.find('.md-write-holder').show();
$form.find('textarea.markdown-area').focus();
$form.find('.md-preview-holder').hide();
markdownToolbar.addClass('active');
markdownPreview.hideReferencedCommands($form);
});
......
import tooltip from '../../vue_shared/directives/tooltip';
import { pluralize } from '../../lib/utils/text_utility';
import icon from '../../vue_shared/components/icon.vue';
export default {
name: 'MRWidgetHeader',
......@@ -9,6 +10,9 @@ export default {
directives: {
tooltip,
},
components: {
icon,
},
computed: {
shouldShowCommitsBehindText() {
return this.mr.divergedCommitsCount > 0;
......@@ -81,10 +85,9 @@ export default {
data-toggle="dropdown"
aria-label="Download as"
role="button">
<i
class="fa fa-download"
aria-hidden="true">
</i>
<icon
name="download">
</icon>
<i
class="fa fa-caret-down"
aria-hidden="true">
......
......@@ -2,13 +2,14 @@
import commitIconSvg from 'icons/_icon_commit.svg';
import userAvatarLink from './user_avatar/user_avatar_link.vue';
import tooltip from '../directives/tooltip';
import Icon from '../../vue_shared/components/icon.vue';
export default {
props: {
/**
* Indicates the existance of a tag.
* Used to render the correct icon, if true will render `fa-tag` icon,
* if false will render `fa-code-fork` icon.
* if false will render a svg sprite fork icon
*/
tag: {
type: Boolean,
......@@ -107,6 +108,7 @@
},
components: {
userAvatarLink,
Icon,
},
created() {
this.commitIconSvg = commitIconSvg;
......@@ -123,11 +125,10 @@
class="fa fa-tag"
aria-hidden="true">
</i>
<i
<icon
v-if="!tag"
class="fa fa-code-fork"
aria-hidden="true">
</i>
name="fork">
</icon>
</div>
<a
......
......@@ -72,7 +72,9 @@
Preview
</a>
</li>
<li class="md-header-toolbar">
<li
class="md-header-toolbar"
:class="{ active: !previewMarkdown }">
<toolbar-button
tag="**"
button-title="Add bold text"
......
......@@ -122,11 +122,17 @@ export default {
return items;
},
showPagination() {
return this.pageInfo.totalPages > 1;
},
},
};
</script>
<template>
<div class="gl-pagination">
<div
v-if="showPagination"
class="gl-pagination"
>
<ul class="pagination clearfix">
<li
v-for="item in getItems"
......
......@@ -9,12 +9,6 @@
padding-left: $contextual-sidebar-width;
}
// Override position: absolute
.right-sidebar {
position: fixed;
height: calc(100% - #{$header-height});
}
.issues-bulk-update.right-sidebar.right-sidebar-expanded .issuable-sidebar-header {
padding: 10px 0 15px;
}
......
......@@ -16,27 +16,18 @@
@mixin set-visible {
transform: translateY(0);
visibility: visible;
opacity: 1;
transition-duration: 100ms, 150ms, 25ms;
transition-delay: 35ms, 50ms, 25ms;
display: block;
}
@mixin set-invisible {
transform: translateY(-10px);
visibility: hidden;
opacity: 0;
transition-property: opacity, transform, visibility;
transition-duration: 70ms, 250ms, 250ms;
transition-timing-function: linear, $dropdown-animation-timing;
transition-delay: 25ms, 50ms, 0ms;
display: none;
}
.open {
.dropdown-menu,
.dropdown-menu-nav {
@include set-visible;
display: block;
min-height: 40px;
@media (max-width: $screen-xs-max) {
......@@ -55,6 +46,11 @@
}
}
// Get search dropdown to line up with other nav dropdowns
.search-input-container .dropdown-menu {
margin-top: 11px;
}
.dropdown-toggle {
padding: 6px 8px 6px 10px;
background-color: $white-light;
......@@ -214,7 +210,6 @@
.dropdown-menu,
.dropdown-menu-nav {
@include set-invisible;
display: block;
position: absolute;
width: auto;
top: 100%;
......
......@@ -74,7 +74,7 @@
}
.md-header-tab {
@media(max-width: $screen-xs-max) {
@media (max-width: $screen-xs-max) {
flex: 1;
width: 100%;
border-bottom: 1px solid $border-color;
......@@ -82,16 +82,23 @@
}
}
.md-header-toolbar {
margin-left: auto;
.nav-links {
li.md-header-toolbar {
margin-left: auto;
display: none;
@media(max-width: $screen-xs-max) {
flex: none;
display: flex;
justify-content: center;
width: 100%;
padding-top: $gl-padding-top;
padding-bottom: $gl-padding-top;
&.active {
display: block;
@media (max-width: $screen-xs-max) {
flex: none;
display: flex;
justify-content: center;
width: 100%;
padding-top: $gl-padding-top;
padding-bottom: $gl-padding-top;
}
}
}
}
......@@ -175,7 +182,7 @@
margin-left: $gl-padding;
margin-right: -5px;
@media(max-width: $screen-xs-max) {
@media (max-width: $screen-xs-max) {
margin-left: 0;
margin-right: 0;
}
......@@ -239,7 +246,7 @@
}
}
@media(max-width: $screen-xs-max) {
@media (max-width: $screen-xs-max) {
.atwho-view-ul {
width: 350px;
}
......
......@@ -90,11 +90,6 @@
.right-sidebar {
border-left: 1px solid $border-color;
height: calc(100% - #{$header-height});
&.affix {
position: fixed;
top: $header-height;
}
}
.with-performance-bar .right-sidebar.affix {
......
......@@ -16,6 +16,10 @@
.commit-sha,
.commit-info {
margin-left: 4px;
.fork-svg {
margin-right: 4px;
}
}
.ref-name {
......@@ -79,7 +83,7 @@
}
.limit-icon {
margin: 0 8px;
margin: 0 4px;
}
.limit-message {
......
......@@ -6,7 +6,7 @@
.cluster-applications-table {
// Wait for the Vue to kick-in and render the applications block
min-height: 302px;
min-height: 400px;
}
.clusters-dropdown-menu {
......
......@@ -122,7 +122,7 @@
}
.right-sidebar {
position: absolute;
position: fixed;
top: $header-height;
bottom: 0;
right: 0;
......@@ -503,7 +503,7 @@
top: $header-height + $performance-bar-height;
.issuable-sidebar {
height: calc(100% - #{$header-height} - #{$performance-bar-height});
height: calc(100% - #{$performance-bar-height});
}
}
......
......@@ -774,6 +774,7 @@
}
}
<<<<<<< HEAD
.mr-widget-icon {
font-size: 22px;
margin: 0 10px 0 0;
......@@ -823,4 +824,8 @@
}
}
}
=======
.fork-sprite {
margin-right: -5px;
>>>>>>> upstream/master
}
......@@ -39,6 +39,10 @@
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
svg {
vertical-align: middle;
}
}
.next-run-cell {
......
......@@ -170,6 +170,12 @@
fill: $gl-text-color-secondary;
}
.sprite {
width: 12px;
height: 12px;
fill: $gl-text-color;
}
.fa {
font-size: 12px;
color: $gl-text-color;
......
......@@ -45,6 +45,10 @@
height: calc(100vh - #{$header-height});
}
.with-performance-bar .ide-view {
height: calc(100vh - #{$header-height});
}
.ide-file-list {
flex: 1;
......
......@@ -108,13 +108,6 @@ input[type="checkbox"]:hover {
// Custom dropdown positioning
.dropdown-menu {
transition-property: opacity, transform;
transition-duration: 250ms, 250ms;
transition-delay: 0ms, 25ms;
transition-timing-function: $dropdown-animation-timing;
transform: translateY(0);
opacity: 0;
display: block;
left: -5px;
}
......@@ -152,13 +145,6 @@ input[type="checkbox"]:hover {
background-color: $nav-badge-bg;
border-color: $border-color;
}
.dropdown-menu {
transition-duration: 100ms, 75ms;
transition-delay: 75ms, 100ms;
transform: translateY(7px);
opacity: 1;
}
}
&.has-value {
......
......@@ -9,10 +9,13 @@ class AutocompleteController < ApplicationController
@users = AutocompleteUsersFinder.new(params: params, current_user: current_user, project: @project, group: @group).execute
render json: UserSerializer.new.represent(@users)
<<<<<<< HEAD
end
def project_groups
render json: @project.invited_groups, only: [:id, :name], methods: [:avatar_url]
=======
>>>>>>> upstream/master
end
def user
......
......@@ -5,9 +5,6 @@ class Projects::BlobController < Projects::ApplicationController
include RendersBlob
include ActionView::Helpers::SanitizeHelper
# Raised when given an invalid file path
InvalidPathError = Class.new(StandardError)
prepend_before_action :authenticate_user!, only: [:edit]
before_action :require_non_empty_project, except: [:new, :create]
......@@ -61,7 +58,6 @@ class Projects::BlobController < Projects::ApplicationController
create_commit(Files::UpdateService, success_path: -> { after_edit_path },
failure_view: :edit,
failure_path: project_blob_path(@project, @id))
rescue Files::UpdateService::FileChangedError
@conflict = true
render :edit
......@@ -132,7 +128,6 @@ class Projects::BlobController < Projects::ApplicationController
def assign_blob_vars
@id = params[:id]
@ref, @path = extract_ref(@id)
rescue InvalidPathError
render_404
end
......
......@@ -269,7 +269,7 @@ module BlobHelper
return if blob.empty?
if blob.raw_binary? || blob.stored_externally?
icon = icon('download')
icon = sprite_icon('download')
title = 'Download'
else
icon = icon('file-code-o')
......
......@@ -63,7 +63,7 @@ module CommitsHelper
# Returns a link formatted as a commit branch link
def commit_branch_link(url, text)
link_to(url, class: 'label label-gray ref-name branch-link') do
icon('code-fork', class: 'append-right-5') + "#{text}"
sprite_icon('fork', size: 16, css_class: 'fork-svg') + "#{text}"
end
end
......
......@@ -46,14 +46,20 @@ module SortingHelper
end
def groups_sort_options_hash
options = {
{
sort_value_name => sort_title_name,
sort_value_name_desc => sort_title_name_desc,
sort_value_recently_created => sort_title_recently_created,
sort_value_oldest_created => sort_title_oldest_created,
sort_value_recently_updated => sort_title_recently_updated,
sort_value_oldest_updated => sort_title_oldest_updated
}
end
options
def admin_groups_sort_options_hash
groups_sort_options_hash.merge(
sort_value_largest_group => sort_title_largest_group
)
end
def member_sort_options_hash
......
......@@ -3,32 +3,19 @@ module Clusters
class Helm < ActiveRecord::Base
self.table_name = 'clusters_applications_helm'
include ::Clusters::Concerns::ApplicationCore
include ::Clusters::Concerns::ApplicationStatus
belongs_to :cluster, class_name: 'Clusters::Cluster', foreign_key: :cluster_id
default_value_for :version, Gitlab::Kubernetes::Helm::HELM_VERSION
validates :cluster, presence: true
after_initialize :set_initial_status
def self.application_name
self.to_s.demodulize.underscore
end
def set_initial_status
return unless not_installable?
self.status = 'installable' if cluster&.platform_kubernetes_active?
end
def name
self.class.application_name
end
def install_command
Gitlab::Kubernetes::Helm::InstallCommand.new(name, true)
Gitlab::Kubernetes::Helm::InstallCommand.new(name, install_helm: true)
end
end
end
......
......@@ -3,41 +3,22 @@ module Clusters
class Ingress < ActiveRecord::Base
self.table_name = 'clusters_applications_ingress'
include ::Clusters::Concerns::ApplicationCore
include ::Clusters::Concerns::ApplicationStatus
belongs_to :cluster, class_name: 'Clusters::Cluster', foreign_key: :cluster_id
validates :cluster, presence: true
default_value_for :ingress_type, :nginx
default_value_for :version, :nginx
after_initialize :set_initial_status
enum ingress_type: {
nginx: 1
}
def self.application_name
self.to_s.demodulize.underscore
end
def set_initial_status
return unless not_installable?
self.status = 'installable' if cluster&.application_helm_installed?
end
def name
self.class.application_name
end
def chart
'stable/nginx-ingress'
end
def install_command
Gitlab::Kubernetes::Helm::InstallCommand.new(name, false, chart)
Gitlab::Kubernetes::Helm::InstallCommand.new(name, chart: chart)
end
end
end
......
module Clusters
module Applications
class Prometheus < ActiveRecord::Base
VERSION = "2.0.0".freeze
self.table_name = 'clusters_applications_prometheus'
include ::Clusters::Concerns::ApplicationCore
include ::Clusters::Concerns::ApplicationStatus
default_value_for :version, VERSION
def chart
'stable/prometheus'
end
def chart_values_file
"#{Rails.root}/vendor/#{name}/values.yaml"
end
def install_command
Gitlab::Kubernetes::Helm::InstallCommand.new(name, chart: chart, chart_values_file: chart_values_file)
end
end
end
end
......@@ -7,7 +7,8 @@ module Clusters
APPLICATIONS = {
Applications::Helm.application_name => Applications::Helm,
Applications::Ingress.application_name => Applications::Ingress
Applications::Ingress.application_name => Applications::Ingress,
Applications::Prometheus.application_name => Applications::Prometheus
}.freeze
belongs_to :user
......@@ -22,6 +23,7 @@ module Clusters
has_one :application_helm, class_name: 'Clusters::Applications::Helm'
has_one :application_ingress, class_name: 'Clusters::Applications::Ingress'
has_one :application_prometheus, class_name: 'Clusters::Applications::Prometheus'
accepts_nested_attributes_for :provider_gcp, update_only: true
accepts_nested_attributes_for :platform_kubernetes, update_only: true
......@@ -64,7 +66,8 @@ module Clusters
def applications
[
application_helm || build_application_helm,
application_ingress || build_application_ingress
application_ingress || build_application_ingress,
application_prometheus || build_application_prometheus
]
end
......
module Clusters
module Concerns
module ApplicationCore
extend ActiveSupport::Concern
included do
belongs_to :cluster, class_name: 'Clusters::Cluster', foreign_key: :cluster_id
validates :cluster, presence: true
after_initialize :set_initial_status
def set_initial_status
return unless not_installable?
self.status = 'installable' if cluster&.application_helm_installed?
end
def self.application_name
self.to_s.demodulize.underscore
end
def name
self.class.application_name
end
end
end
end
end
......@@ -9,7 +9,6 @@ module DiscussionOnDiff
:original_line_code,
:diff_file,
:diff_line,
:for_line?,
:active?,
:created_at_diff?,
......@@ -39,17 +38,16 @@ module DiscussionOnDiff
# Returns an array of at most 16 highlighted lines above a diff note
def truncated_diff_lines(highlight: true)
lines = highlight ? highlighted_diff_lines : diff_lines
initial_line_index = [diff_line.index - NUMBER_OF_TRUNCATED_DIFF_LINES + 1, 0].max
prev_lines = []
lines.each do |line|
lines[initial_line_index..diff_line.index].each do |line|
if line.meta?
prev_lines.clear
else
prev_lines << line
break if for_line?(line)
prev_lines.shift if prev_lines.length >= NUMBER_OF_TRUNCATED_DIFF_LINES
end
end
......
......@@ -14,10 +14,6 @@ module NoteOnDiff
raise NotImplementedError
end
def for_line?(line)
raise NotImplementedError
end
def original_line_code
raise NotImplementedError
end
......
......@@ -2,6 +2,7 @@
#
# After migrating issues_enabled merge_requests_enabled builds_enabled snippets_enabled and wiki_enabled
# fields to a new table "project_features", support for the old fields is still needed in the API.
require 'gitlab/utils'
module ProjectFeaturesCompatibility
extend ActiveSupport::Concern
......
......@@ -26,7 +26,7 @@ class DiffNote < Note
before_validation :set_original_position, on: :create
before_validation :update_position, on: :create, if: :on_text?
before_validation :set_line_code
before_validation :set_line_code, if: :on_text?
after_save :keep_around_commits
def discussion_class(*)
......@@ -66,10 +66,6 @@ class DiffNote < Note
@diff_line ||= diff_file&.line_for_position(self.original_position)
end
def for_line?(line)
diff_file.position(line) == self.original_position
end
def original_line_code
return unless on_text?
......
......@@ -72,7 +72,7 @@ class Event < ActiveRecord::Base
# We're using preload for "push_event_payload" as otherwise the association
# is not always available (depending on the query being built).
includes(:author, :project, project: :namespace)
.preload(:push_event_payload, target: :author)
.preload(:target, :push_event_payload)
end
scope :for_milestone_id, ->(milestone_id) { where(target_type: "Milestone", target_id: milestone_id) }
......
......@@ -10,6 +10,8 @@ class Identity < ActiveRecord::Base
validates :extern_uid, allow_blank: true, uniqueness: { scope: :provider, case_sensitive: false }
validates :user_id, uniqueness: { scope: :provider }
before_save :ensure_normalized_extern_uid, if: :extern_uid_changed?
scope :with_provider, ->(provider) { where(provider: provider) }
scope :with_extern_uid, ->(provider, extern_uid) do
iwhere(extern_uid: normalize_uid(provider, extern_uid)).with_provider(provider)
......@@ -26,4 +28,12 @@ class Identity < ActiveRecord::Base
uid.to_s
end
end
private
def ensure_normalized_extern_uid
return if extern_uid.nil?
self.extern_uid = Identity.normalize_uid(self.provider, self.extern_uid)
end
end
......@@ -43,11 +43,7 @@ class LegacyDiffNote < Note
end
def diff_line
@diff_line ||= diff_file.line_for_line_code(self.line_code) if diff_file
end
def for_line?(line)
line.discussable? && diff_file.line_code(line) == self.line_code
@diff_line ||= diff_file&.line_for_line_code(self.line_code)
end
def original_line_code
......
......@@ -960,7 +960,9 @@ class Project < ActiveRecord::Base
def send_move_instructions(old_path_with_namespace)
# New project path needs to be committed to the DB or notification will
# retrieve stale information
run_after_commit { NotificationService.new.project_was_moved(self, old_path_with_namespace) }
run_after_commit do
NotificationService.new.project_was_moved(self, old_path_with_namespace)
end
end
def owner
......@@ -972,15 +974,19 @@ class Project < ActiveRecord::Base
end
def execute_hooks(data, hooks_scope = :push_hooks)
hooks.public_send(hooks_scope).each do |hook| # rubocop:disable GitlabSecurity/PublicSend
hook.async_execute(data, hooks_scope.to_s)
run_after_commit_or_now do
hooks.public_send(hooks_scope).each do |hook| # rubocop:disable GitlabSecurity/PublicSend
hook.async_execute(data, hooks_scope.to_s)
end
end
end
def execute_services(data, hooks_scope = :push_hooks)
# Call only service hooks that are active for this scope
services.public_send(hooks_scope).each do |service| # rubocop:disable GitlabSecurity/PublicSend
service.async_execute(data)
run_after_commit_or_now do
services.public_send(hooks_scope).each do |service| # rubocop:disable GitlabSecurity/PublicSend
service.async_execute(data)
end
end
end
......@@ -1158,7 +1164,7 @@ class Project < ActiveRecord::Base
def change_head(branch)
if repository.branch_exists?(branch)
repository.before_change_head
repository.write_ref('HEAD', "refs/heads/#{branch}", force: true)
repository.write_ref('HEAD', "refs/heads/#{branch}")
repository.copy_gitattributes(branch)
repository.after_change_head
reload_default_branch
......
......@@ -24,7 +24,6 @@ class Repository
attr_accessor :full_path, :disk_path, :project, :is_wiki
delegate :ref_name_for_sha, to: :raw_repository
delegate :write_ref, to: :raw_repository
CreateTreeError = Class.new(StandardError)
......@@ -263,10 +262,11 @@ class Repository
# This will still fail if the file is corrupted (e.g. 0 bytes)
begin
write_ref(keep_around_ref_name(sha), sha, force: true)
rescue Gitlab::Git::Repository::GitError => ex
# Necessary because https://gitlab.com/gitlab-org/gitlab-ce/issues/20156
return true if ex.message =~ /Failed to create locked file/ && ex.message =~ /File exists/
write_ref(keep_around_ref_name(sha), sha)
rescue Rugged::ReferenceError => ex
Rails.logger.error "Unable to create #{REF_KEEP_AROUND} reference for repository #{path}: #{ex}"
rescue Rugged::OSError => ex
raise unless ex.message =~ /Failed to create locked file/ && ex.message =~ /File exists/
Rails.logger.error "Unable to create #{REF_KEEP_AROUND} reference for repository #{path}: #{ex}"
end
......@@ -276,6 +276,10 @@ class Repository
ref_exists?(keep_around_ref_name(sha))
end
def write_ref(ref_path, sha)
rugged.references.create(ref_path, sha, force: true)
end
def diverging_commit_counts(branch)
root_ref_hash = raw_repository.commit(root_ref).id
cache.fetch(:"diverging_commit_counts_#{branch.name}") do
......@@ -1064,7 +1068,7 @@ class Repository
end
def create_ref(ref, ref_path)
write_ref(ref_path, ref)
raw_repository.write_ref(ref_path, ref)
end
def ls_files(ref)
......
......@@ -19,8 +19,11 @@ class User < ActiveRecord::Base
include IgnorableColumn
include BulkMemberAccessLoad
include BlocksJsonSerialization
<<<<<<< HEAD
prepend EE::User
=======
>>>>>>> upstream/master
DEFAULT_NOTIFICATION_LEVEL = :participating
......
......@@ -7,7 +7,7 @@ class MergeRequestSerializer < BaseSerializer
case opts[:serializer]
when 'basic', 'sidebar'
MergeRequestBasicEntity
when 'widget'
else # It's 'widget'
MergeRequestWidgetEntity
end
......
......@@ -18,7 +18,7 @@ module Clusters
end
def helm_api
@helm_api ||= Gitlab::Kubernetes::Helm.new(kubeclient)
@helm_api ||= Gitlab::Kubernetes::Helm::Api.new(kubeclient)
end
def install_command
......
module Files
class BaseService < Commits::CreateService
FileChangedError = Class.new(StandardError)
def initialize(*args)
super
@author_email = params[:author_email]
@author_name = params[:author_name]
@commit_message = params[:commit_message]
@last_commit_sha = params[:last_commit_sha]
@file_path = params[:file_path]
@previous_path = params[:previous_path]
......@@ -13,5 +16,16 @@ module Files
@file_content = params[:file_content]
@file_content = Base64.decode64(@file_content) if params[:file_content_encoding] == 'base64'
end
def file_has_changed?(path, commit_id)
return false unless commit_id
last_commit = Gitlab::Git::Commit
.last_for_path(@start_project.repository, @start_branch, path)
return false unless last_commit
last_commit.sha != commit_id
end
end
end
......@@ -11,5 +11,15 @@ module Files
start_project: @start_project,
start_branch_name: @start_branch)
end
private
def validate!
super
if file_has_changed?(@file_path, @last_commit_sha)
raise FileChangedError, "You are attempting to delete a file that has been previously updated."
end
end
end
end
module Files
class MultiService < Files::BaseService
UPDATE_FILE_ACTIONS = %w(update move delete).freeze
def create_commit!
repository.multi_action(
user: current_user,
......@@ -20,6 +22,7 @@ module Files
params[:actions].each do |action|
validate_action!(action)
validate_file_status!(action)
end
end
......@@ -28,5 +31,15 @@ module Files
raise_error("Unknown action '#{action[:action]}'")
end
end
def validate_file_status!(action)
return unless UPDATE_FILE_ACTIONS.include?(action[:action])
file_path = action[:previous_path] || action[:file_path]
if file_has_changed?(file_path, action[:last_commit_id])
raise_error("The file has changed since you started editing it: #{file_path}")
end
end
end
end
module Files
class UpdateService < Files::BaseService
FileChangedError = Class.new(StandardError)
def initialize(*args)
super
@last_commit_sha = params[:last_commit_sha]
end
def create_commit!
repository.update_file(current_user, @file_path, @file_content,
message: @commit_message,
......@@ -21,21 +13,10 @@ module Files
private
def file_has_changed?
return false unless @last_commit_sha && last_commit
@last_commit_sha != last_commit.sha
end
def last_commit
@last_commit ||= Gitlab::Git::Commit
.last_for_path(@start_project.repository, @start_branch, @file_path)
end
def validate!
super
if file_has_changed?
if file_has_changed?(@file_path, @last_commit_sha)
raise FileChangedError, "You are attempting to update a file that has changed since you started editing it."
end
end
......
......@@ -5,7 +5,7 @@ module Projects
if fork_source = @project.fork_source
fork_source.lfs_objects.find_each do |lfs_object|
lfs_object.projects << @project
lfs_object.projects << @project unless lfs_object.projects.include?(@project)
end
refresh_forks_count(fork_source)
......
......@@ -3,17 +3,24 @@ module Search
include Gitlab::CurrentSettings
attr_accessor :current_user, :params
attr_reader :default_project_filter
def initialize(user, params)
@current_user, @params = user, params.dup
@default_project_filter = true
end
def execute
<<<<<<< HEAD
if current_application_settings.elasticsearch_search?
Gitlab::Elastic::SearchResults.new(current_user, params[:search], elastic_projects, elastic_global)
else
Gitlab::SearchResults.new(current_user, projects, params[:search])
end
=======
Gitlab::SearchResults.new(current_user, projects, params[:search],
default_project_filter: default_project_filter)
>>>>>>> upstream/master
end
def projects
......
......@@ -5,6 +5,7 @@ module Search
def initialize(user, group, params)
super(user, params)
@default_project_filter = false
@group = group
end
......
......@@ -11,23 +11,7 @@
.search-field-holder
= search_field_tag :name, project_name, class: "form-control search-text-input js-search-input", autofocus: true, spellcheck: false, placeholder: 'Search by name'
= icon("search", class: "search-icon")
.dropdown
- toggle_text = @sort.present? ? sort_options_hash[@sort] : sort_title_recently_created
= dropdown_toggle(toggle_text, { toggle: 'dropdown' })
%ul.dropdown-menu.dropdown-menu-align-right
%li.dropdown-header
Sort by
%li
= link_to admin_groups_path(sort: sort_value_recently_created, name: project_name) do
= sort_title_recently_created
= link_to admin_groups_path(sort: sort_value_oldest_created, name: project_name) do
= sort_title_oldest_created
= link_to admin_groups_path(sort: sort_value_recently_updated, name: project_name) do
= sort_title_recently_updated
= link_to admin_groups_path(sort: sort_value_oldest_updated, name: project_name) do
= sort_title_oldest_updated
= link_to admin_groups_path(sort: sort_value_largest_group, name: project_name) do
= sort_title_largest_group
= render "shared/groups/dropdown", options_hash: admin_groups_sort_options_hash
= link_to new_admin_group_path, class: "btn btn-new" do
New group
%ul.content-list
......
- event = last_push_event
- if event && show_last_push_widget?(event)
.row-content-block.top-block.hidden-xs.white
.event-last-push
.event-last-push-text
%span= s_("LastPushEvent|You pushed to")
%strong
= link_to event.ref_name, project_commits_path(event.project, event.ref_name), class: 'ref-name'
%div{ class: container_class }
.row-content-block.top-block.hidden-xs.white
.event-last-push
.event-last-push-text
%span= s_("LastPushEvent|You pushed to")
%strong
= link_to event.ref_name, project_commits_path(event.project, event.ref_name), class: 'ref-name'
- if event.project != @project
%span= s_("LastPushEvent|at")
%strong= link_to_project event.project
- if event.project != @project
%span= s_("LastPushEvent|at")
%strong= link_to_project event.project
#{time_ago_with_tooltip(event.created_at)}
#{time_ago_with_tooltip(event.created_at)}
.pull-right
= link_to new_mr_path_from_push_event(event), title: _("New merge request"), class: "btn btn-info btn-sm" do
#{ _('Create merge request') }
.pull-right
= link_to new_mr_path_from_push_event(event), title: _("New merge request"), class: "btn btn-info btn-sm" do
#{ _('Create merge request') }
......@@ -17,7 +17,7 @@
%a.js-md-preview-button{ href: "#md-preview-holder", tabindex: -1 }
Preview
%li.md-header-toolbar
%li.md-header-toolbar.active
= markdown_toolbar_button({ icon: "bold", data: { "md-tag" => "**" }, title: "Add bold text" })
= markdown_toolbar_button({ icon: "italic", data: { "md-tag" => "*" }, title: "Add italic text" })
= markdown_toolbar_button({ icon: "quote", data: { "md-tag" => "> ", "md-prepend" => true }, title: "Insert a quote" })
......
......@@ -18,7 +18,7 @@
.tree-controls
= link_to download_project_job_artifacts_path(@project, @build),
rel: 'nofollow', download: '', class: 'btn btn-default download' do
= icon('download')
= sprite_icon('download')
Download artifacts archive
.tree-content-holder
......
......@@ -3,7 +3,7 @@
.file-holder-bottom-radius.file-holder.file.append-bottom-default
.js-file-title.file-title.clearfix{ data: { current_action: action } }
.editor-ref
= icon('code-fork')
= sprite_icon('fork', size: 12)
= ref
%span.editor-file-name
- if current_action?(:edit) || current_action?(:update)
......
......@@ -2,6 +2,6 @@
.center.render-error.vertical-center
= link_to blob_raw_path do
%h1.light
= icon('download')
= sprite_icon('download')
%h4
Download (#{number_to_human_size(viewer.blob.raw_size)})
......@@ -8,7 +8,8 @@
%li{ class: "js-branch-#{branch.name}" }
%div
= link_to project_tree_path(@project, branch.name), class: 'item-title str-truncated ref-name' do
= icon('code-fork', class: 'append-right-5') + "#{branch.name}"
= sprite_icon('fork', size: 12)
= branch.name
&nbsp;
- if branch.name == @repository.root_ref
%span.label.label-primary default
......
......@@ -3,7 +3,7 @@
- if !project.empty_repo? && can?(current_user, :download_code, project)
.project-action-button.dropdown.inline>
%button.btn.has-tooltip{ title: s_('DownloadSource|Download'), 'data-toggle' => 'dropdown', 'aria-label' => s_('DownloadSource|Download') }
= icon('download')
= sprite_icon('download')
= icon("caret-down")
%span.sr-only= _('Select Archive Format')
%ul.dropdown-menu.dropdown-menu-align-right{ role: 'menu' }
......
......@@ -22,7 +22,7 @@
- if ref
- if job.ref
.icon-container
= job.tag? ? icon('tag') : icon('code-fork')
= job.tag? ? icon('tag') : sprite_icon('fork', css_class: 'sprite')
= link_to job.ref, project_ref_path(job.project, job.ref), class: "ref-name"
- else
.light none
......@@ -96,7 +96,7 @@
.pull-right
- if can?(current_user, :read_build, job) && job.artifacts?
= link_to download_project_job_artifacts_path(job.project, job), rel: 'nofollow', download: '', title: 'Download artifacts', class: 'btn btn-build' do
= icon('download')
= sprite_icon('download')
- if can?(current_user, :update_build, job)
- if job.active?
= link_to cancel_project_job_path(job.project, job, return_to: request.original_url), method: :post, title: 'Cancel', class: 'btn btn-build' do
......
......@@ -9,6 +9,7 @@
.edit-cluster-form.js-edit-cluster-form{ data: { status_path: status_path,
install_helm_path: install_applications_namespace_project_cluster_path(@cluster.project.namespace, @cluster.project, @cluster, :helm),
install_ingress_path: install_applications_namespace_project_cluster_path(@cluster.project.namespace, @cluster.project, @cluster, :ingress),
install_prometheus_path: install_applications_namespace_project_cluster_path(@cluster.project.namespace, @cluster.project, @cluster, :prometheus),
toggle_status: @cluster.enabled? ? 'true': 'false',
cluster_status: @cluster.status_name,
cluster_status_reason: @cluster.status_reason,
......
.has-tooltip{ class: "limit-box limit-box-#{objects} prepend-left-5", data: { title: "Project has too many #{label_for_message} to search"} }
.limit-icon
- if objects == :branch
= icon('code-fork')
= sprite_icon('fork', size: 12)
- else
= icon('tag')
.limit-message
......
......@@ -2,7 +2,7 @@
.branch-commit
- if deployment.ref
%span.icon-container
= deployment.tag? ? icon('tag') : icon('code-fork')
= deployment.tag? ? icon('tag') : sprite_icon('fork', css_class: 'sprite')
= link_to deployment.ref, project_ref_path(@project, deployment.ref), class: "ref-name"
.icon-container.commit-icon
= custom_icon("icon_commit")
......
......@@ -2,7 +2,7 @@
- if @forked_project && !@forked_project.saved?
.alert.alert-danger.alert-block
%h4
%i.fa.fa-code-fork
= sprite_icon('fork', size: 16)
Fork Error!
%p
You tried to fork
......@@ -21,5 +21,4 @@
%p
= link_to new_project_fork_path(@project), title: "Fork", class: "btn" do
%i.fa.fa-code-fork
Try to fork again
......@@ -19,7 +19,7 @@
- if ref
- if generic_commit_status.ref
.icon-container
= generic_commit_status.tags.any? ? icon('tag') : icon('code-fork')
= generic_commit_status.tags.any? ? icon('tag') : sprite_icon('fork', size: 10)
= link_to generic_commit_status.ref, project_commits_path(generic_commit_status.project, generic_commit_status.ref)
- else
.light none
......
......@@ -30,7 +30,7 @@
%span.project-ref-path
&nbsp;
= link_to project_ref_path(merge_request.project, merge_request.target_branch), class: 'ref-name' do
= icon('code-fork')
= sprite_icon('fork', size: 12, css_class: 'fork-sprite')
= merge_request.target_branch
- if merge_request.labels.any?
&nbsp;
......
......@@ -3,7 +3,7 @@
%td
= pipeline_schedule.description
%td.branch-name-cell
= icon('code-fork')
= sprite_icon('fork', size: 12)
- if pipeline_schedule.ref.present?
= link_to pipeline_schedule.ref, project_ref_path(@project, pipeline_schedule.ref), class: "ref-name"
%td
......
<<<<<<< HEAD
.tree-content-holder.js-tree-content{ 'data-logs-path': @logs_path, 'data-path-locks-available': (@project.feature_available?(:file_locks) ? 'true' : 'false'), 'data-path-locks-toggle': toggle_project_path_locks_path(@project), 'data-path-locks-path': @path }
=======
.tree-content-holder.js-tree-content{ 'data-logs-path': @logs_path }
>>>>>>> upstream/master
.table-holder
%table.table#tree-slider{ class: "table_#{@hex_path} tree-table" }
%thead
......
......@@ -73,7 +73,10 @@
= link_to ide_edit_path(@project, @id), class: 'btn btn-default' do
= ide_edit_text
<<<<<<< HEAD
= lock_file_link(html_options: { class: 'btn path-lock' })
=======
>>>>>>> upstream/master
= link_to s_('Commits|History'), project_commits_path(@project, @id), class: 'btn'
= render 'projects/find_file_link'
......
......@@ -6,6 +6,12 @@
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, project_commits_url(@project, @ref, rss_url_options), title: "#{@project.name}:#{@ref} commits")
<<<<<<< HEAD
%div{ class: [(container_class), ("limit-container-width" unless fluid_layout)] }
= render 'projects/last_push'
=======
= render 'projects/last_push'
%div{ class: [(container_class), ("limit-container-width" unless fluid_layout)] }
>>>>>>> upstream/master
= render 'projects/files', commit: @last_commit, project: @project, ref: @ref, content_url: project_tree_path(@project, @id)
- options_hash = local_assigns.fetch(:options_hash, groups_sort_options_hash)
- show_archive_options = local_assigns.fetch(:show_archive_options, false)
- if @sort.present?
- default_sort_by = @sort
......@@ -10,12 +11,12 @@
.dropdown.inline.js-group-filter-dropdown-wrap.append-right-10
%button.dropdown-toggle{ type: 'button', 'data-toggle' => 'dropdown' }
%span.dropdown-label
= sort_options_hash[default_sort_by]
= options_hash[default_sort_by]
= icon('chevron-down')
%ul.dropdown-menu.dropdown-menu-align-right.dropdown-menu-selectable
%li.dropdown-header
= _("Sort by")
- groups_sort_options_hash.each do |value, title|
- options_hash.each do |value, title|
%li.js-filter-sort-order
= link_to filter_groups_path(sort: value), class: ("is-active" if default_sort_by == value) do
= title
......
......@@ -52,7 +52,7 @@
= render_project_pipeline_status(project.pipeline_status)
- if forks
%span.prepend-left-10
= icon('code-fork')
= sprite_icon('fork')
= number_with_delimiter(project.forks_count)
- if stars
%span.prepend-left-10
......
......@@ -23,10 +23,13 @@ class RepositoryImportWorker
raise result[:message] if result[:status] == :error
project.after_import
<<<<<<< HEAD
# Explicitly enqueue mirror for update so
# that upstream remote is created and fetched
project.force_import_job! if project.mirror?
=======
>>>>>>> upstream/master
end
private
......
---
title: 'Validate file status when commiting multiple files'
merge_request: 15922
author:
type: added
---
title: Fix N+1 query when displaying events
title: Improve search query for merge requests.
merge_request:
author:
type: performance
---
title: Disable Vue pagination when only one page of content is available
merge_request: 15999
author: Mario de la Ossa
type: fixed
---
title: Enable ordering of groups and their children by name
merge_request:
author:
type: added
---
title: Add optional search param for Merge Requests API
merge_request:
author:
type: fixed
---
title: Hide markdown toolbar in preview mode
merge_request:
author:
type: changed
---
title: Add Prometheus to available Cluster applications
merge_request: 15895
author:
type: added
---
title: Don't link LFS objects to a project when unlinking forks when they were already
linked
merge_request: 16006
author:
type: fixed
---
title: Improve performance of MR discussions on large diffs
merge_request:
author:
type: performance
---
title: Execute project hooks and services after commit when moving an issue
merge_request:
author:
type: fixed
---
title: Last push event widget width for fixed layout
merge_request: 15862
author: George Tsiolis
type: fixed
---
title: Normalizing Identity extern_uid when saving the record
merge_request:
author:
type: fixed
---
title: Add index on namespaces lower(name) for UsersController#exists
merge_request:
author:
type: performance
---
title: Reduce the number of buckets in gitlab_cache_operation_duration_seconds metric
merge_request: 15881
author:
type: changed
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment