Commit 15483879 authored by Nick Thomas's avatar Nick Thomas

Merge remote-tracking branch 'ce/master' into nt/ce-to-ee-thursday

parents ccbd665a f96e1bf1
...@@ -264,7 +264,6 @@ rake karma: ...@@ -264,7 +264,6 @@ rake karma:
cache: cache:
paths: paths:
- vendor/ruby - vendor/ruby
- node_modules
stage: test stage: test
<<: *use-db <<: *use-db
<<: *dedicated-runner <<: *dedicated-runner
...@@ -363,9 +362,6 @@ coverage: ...@@ -363,9 +362,6 @@ coverage:
lint:javascript: lint:javascript:
<<: *dedicated-runner <<: *dedicated-runner
cache:
paths:
- node_modules/
stage: test stage: test
before_script: [] before_script: []
script: script:
...@@ -373,9 +369,6 @@ lint:javascript: ...@@ -373,9 +369,6 @@ lint:javascript:
lint:javascript:report: lint:javascript:report:
<<: *dedicated-runner <<: *dedicated-runner
cache:
paths:
- node_modules/
stage: post-test stage: post-test
before_script: [] before_script: []
script: script:
......
import CANCELED_SVG from 'icons/_icon_status_canceled_borderless.svg';
import CREATED_SVG from 'icons/_icon_status_created_borderless.svg';
import FAILED_SVG from 'icons/_icon_status_failed_borderless.svg';
import MANUAL_SVG from 'icons/_icon_status_manual_borderless.svg';
import PENDING_SVG from 'icons/_icon_status_pending_borderless.svg';
import RUNNING_SVG from 'icons/_icon_status_running_borderless.svg';
import SKIPPED_SVG from 'icons/_icon_status_skipped_borderless.svg';
import SUCCESS_SVG from 'icons/_icon_status_success_borderless.svg';
import WARNING_SVG from 'icons/_icon_status_warning_borderless.svg';
const StatusIconEntityMap = {
icon_status_canceled: CANCELED_SVG,
icon_status_created: CREATED_SVG,
icon_status_failed: FAILED_SVG,
icon_status_manual: MANUAL_SVG,
icon_status_pending: PENDING_SVG,
icon_status_running: RUNNING_SVG,
icon_status_skipped: SKIPPED_SVG,
icon_status_success: SUCCESS_SVG,
icon_status_warning: WARNING_SVG,
};
export {
CANCELED_SVG,
CREATED_SVG,
FAILED_SVG,
MANUAL_SVG,
PENDING_SVG,
RUNNING_SVG,
SKIPPED_SVG,
SUCCESS_SVG,
WARNING_SVG,
StatusIconEntityMap as default,
};
...@@ -19,7 +19,11 @@ const ResolveBtn = Vue.extend({ ...@@ -19,7 +19,11 @@ const ResolveBtn = Vue.extend({
data: function () { data: function () {
return { return {
discussions: CommentsStore.state, discussions: CommentsStore.state,
<<<<<<< HEAD
loading: false, loading: false,
=======
loading: false
>>>>>>> ce/master
}; };
}, },
watch: { watch: {
......
...@@ -156,13 +156,13 @@ const ShortcutsBlob = require('./shortcuts_blob'); ...@@ -156,13 +156,13 @@ const ShortcutsBlob = require('./shortcuts_blob');
case 'projects:milestones:new': case 'projects:milestones:new':
case 'projects:milestones:edit': case 'projects:milestones:edit':
case 'projects:milestones:update': case 'projects:milestones:update':
case 'groups:milestones:new':
case 'groups:milestones:edit':
case 'groups:milestones:update':
new ZenMode(); new ZenMode();
new gl.DueDateSelectors(); new gl.DueDateSelectors();
new gl.GLForm($('.milestone-form')); new gl.GLForm($('.milestone-form'));
break; break;
case 'groups:milestones:new':
new ZenMode();
break;
case 'projects:compare:show': case 'projects:compare:show':
new gl.Diff(); new gl.Diff();
break; break;
...@@ -389,9 +389,14 @@ const ShortcutsBlob = require('./shortcuts_blob'); ...@@ -389,9 +389,14 @@ const ShortcutsBlob = require('./shortcuts_blob');
case 'admin': case 'admin':
new Admin(); new Admin();
switch (path[1]) { switch (path[1]) {
<<<<<<< HEAD
case 'application_settings': case 'application_settings':
case 'cohorts': case 'cohorts':
new gl.ApplicationSettings(); new gl.ApplicationSettings();
=======
case 'cohorts':
new gl.UsagePing();
>>>>>>> ce/master
break; break;
case 'groups': case 'groups':
new UsersSelect(); new UsersSelect();
......
...@@ -2,10 +2,12 @@ const DATA_TRIGGER = 'data-dropdown-trigger'; ...@@ -2,10 +2,12 @@ const DATA_TRIGGER = 'data-dropdown-trigger';
const DATA_DROPDOWN = 'data-dropdown'; const DATA_DROPDOWN = 'data-dropdown';
const SELECTED_CLASS = 'droplab-item-selected'; const SELECTED_CLASS = 'droplab-item-selected';
const ACTIVE_CLASS = 'droplab-item-active'; const ACTIVE_CLASS = 'droplab-item-active';
const IGNORE_CLASS = 'droplab-item-ignore';
export { export {
DATA_TRIGGER, DATA_TRIGGER,
DATA_DROPDOWN, DATA_DROPDOWN,
SELECTED_CLASS, SELECTED_CLASS,
ACTIVE_CLASS, ACTIVE_CLASS,
IGNORE_CLASS,
}; };
/* eslint-disable */ /* eslint-disable */
import utils from './utils'; import utils from './utils';
import { SELECTED_CLASS } from './constants'; import { SELECTED_CLASS, IGNORE_CLASS } from './constants';
var DropDown = function(list) { var DropDown = function(list) {
this.currentIndex = 0; this.currentIndex = 0;
...@@ -36,6 +36,7 @@ Object.assign(DropDown.prototype, { ...@@ -36,6 +36,7 @@ Object.assign(DropDown.prototype, {
clickEvent: function(e) { clickEvent: function(e) {
if (e.target.tagName === 'UL') return; if (e.target.tagName === 'UL') return;
if (e.target.classList.contains(IGNORE_CLASS)) return;
var selected = utils.closest(e.target, 'LI'); var selected = utils.closest(e.target, 'LI');
if (!selected) return; if (!selected) return;
......
...@@ -38,6 +38,9 @@ window.DropzoneInput = (function() { ...@@ -38,6 +38,9 @@ window.DropzoneInput = (function() {
"opacity": 0, "opacity": 0,
"display": "none" "display": "none"
}); });
if (!project_uploads_path) return;
dropzone = form_dropzone.dropzone({ dropzone = form_dropzone.dropzone({
url: project_uploads_path, url: project_uploads_path,
dictDefaultMessage: "", dictDefaultMessage: "",
...@@ -133,8 +136,11 @@ window.DropzoneInput = (function() { ...@@ -133,8 +136,11 @@ window.DropzoneInput = (function() {
const textarea = child.get(0); const textarea = child.get(0);
caretStart = textarea.selectionStart; caretStart = textarea.selectionStart;
caretEnd = textarea.selectionEnd; caretEnd = textarea.selectionEnd;
<<<<<<< HEAD
caretStart = textarea.selectionStart; caretStart = textarea.selectionStart;
caretEnd = textarea.selectionEnd; caretEnd = textarea.selectionEnd;
=======
>>>>>>> ce/master
textEnd = $(child).val().length; textEnd = $(child).val().length;
beforeSelection = $(child).val().substring(0, caretStart); beforeSelection = $(child).val().substring(0, caretStart);
afterSelection = $(child).val().substring(caretEnd, textEnd); afterSelection = $(child).val().substring(caretEnd, textEnd);
......
<script>
/** /**
* Renders the external url link in environments table. * Renders the external url link in environments table.
*/ */
...@@ -5,7 +6,7 @@ export default { ...@@ -5,7 +6,7 @@ export default {
props: { props: {
externalUrl: { externalUrl: {
type: String, type: String,
default: '', required: true,
}, },
}, },
...@@ -14,17 +15,19 @@ export default { ...@@ -14,17 +15,19 @@ export default {
return 'Open'; return 'Open';
}, },
}, },
};
template: ` </script>
<template>
<a <a
class="btn external-url has-tooltip" class="btn external-url has-tooltip"
data-container="body" data-container="body"
:href="externalUrl"
target="_blank" target="_blank"
rel="noopener noreferrer nofollow" rel="noopener noreferrer nofollow"
:title="title" :title="title"
:aria-label="title"> :aria-label="title"
<i class="fa fa-external-link" aria-hidden="true"></i> :href="externalUrl">
<i
class="fa fa-external-link"
aria-hidden="true" />
</a> </a>
`, </template>
};
...@@ -7,10 +7,10 @@ ...@@ -7,10 +7,10 @@
import Timeago from 'timeago.js'; import Timeago from 'timeago.js';
import '../../lib/utils/text_utility'; import '../../lib/utils/text_utility';
import ActionsComponent from './environment_actions'; import ActionsComponent from './environment_actions';
import ExternalUrlComponent from './environment_external_url'; import ExternalUrlComponent from './environment_external_url.vue';
import StopComponent from './environment_stop'; import StopComponent from './environment_stop.vue';
import RollbackComponent from './environment_rollback'; import RollbackComponent from './environment_rollback';
import TerminalButtonComponent from './environment_terminal_button'; import TerminalButtonComponent from './environment_terminal_button.vue';
import MonitoringButtonComponent from './environment_monitoring'; import MonitoringButtonComponent from './environment_monitoring';
import CommitComponent from '../../vue_shared/components/commit'; import CommitComponent from '../../vue_shared/components/commit';
import eventHub from '../event_hub'; import eventHub from '../event_hub';
......
...@@ -21,7 +21,6 @@ export default { ...@@ -21,7 +21,6 @@ export default {
class="btn monitoring-url has-tooltip" class="btn monitoring-url has-tooltip"
data-container="body" data-container="body"
:href="monitoringUrl" :href="monitoringUrl"
target="_blank"
rel="noopener noreferrer nofollow" rel="noopener noreferrer nofollow"
:title="title" :title="title"
:aria-label="title"> :aria-label="title">
......
<script>
/* global Flash */ /* global Flash */
/* eslint-disable no-new, no-alert */ /* eslint-disable no-new, no-alert */
/** /**
...@@ -51,17 +52,23 @@ export default { ...@@ -51,17 +52,23 @@ export default {
} }
}, },
}, },
};
template: ` </script>
<button type="button" <template>
<button
type="button"
class="btn stop-env-link has-tooltip" class="btn stop-env-link has-tooltip"
data-container="body" data-container="body"
@click="onClick" @click="onClick"
:disabled="isLoading" :disabled="isLoading"
:title="title" :title="title"
:aria-label="title"> :aria-label="title">
<i class="fa fa-stop stop-env-icon" aria-hidden="true"></i> <i
<i v-if="isLoading" class="fa fa-spinner fa-spin" aria-hidden="true"></i> class="fa fa-stop stop-env-icon"
aria-hidden="true" />
<i
v-if="isLoading"
class="fa fa-spinner fa-spin"
aria-hidden="true" />
</button> </button>
`, </template>
};
<script>
/** /**
* Renders a terminal button to open a web terminal. * Renders a terminal button to open a web terminal.
* Used in environments table. * Used in environments table.
...@@ -24,14 +25,15 @@ export default { ...@@ -24,14 +25,15 @@ export default {
return 'Terminal'; return 'Terminal';
}, },
}, },
};
template: ` </script>
<a class="btn terminal-button has-tooltip" <template>
<a
class="btn terminal-button has-tooltip"
data-container="body" data-container="body"
:title="title" :title="title"
:aria-label="title" :aria-label="title"
:href="terminalPath"> :href="terminalPath"
${terminalIconSvg} v-html="terminalIconSvg">
</a> </a>
`, </template>
};
...@@ -2,8 +2,7 @@ import Filter from '~/droplab/plugins/filter'; ...@@ -2,8 +2,7 @@ import Filter from '~/droplab/plugins/filter';
require('./filtered_search_dropdown'); require('./filtered_search_dropdown');
(() => { class DropdownHint extends gl.FilteredSearchDropdown {
class DropdownHint extends gl.FilteredSearchDropdown {
constructor(droplab, dropdown, input, filter) { constructor(droplab, dropdown, input, filter) {
super(droplab, dropdown, input, filter); super(droplab, dropdown, input, filter);
this.config = { this.config = {
...@@ -76,8 +75,7 @@ require('./filtered_search_dropdown'); ...@@ -76,8 +75,7 @@ require('./filtered_search_dropdown');
init() { init() {
this.droplab.addHook(this.input, this.dropdown, [Filter], this.config).init(); this.droplab.addHook(this.input, this.dropdown, [Filter], this.config).init();
} }
} }
window.gl = window.gl || {}; window.gl = window.gl || {};
gl.DropdownHint = DropdownHint; gl.DropdownHint = DropdownHint;
})();
...@@ -5,8 +5,7 @@ import Filter from '~/droplab/plugins/filter'; ...@@ -5,8 +5,7 @@ import Filter from '~/droplab/plugins/filter';
require('./filtered_search_dropdown'); require('./filtered_search_dropdown');
(() => { class DropdownNonUser extends gl.FilteredSearchDropdown {
class DropdownNonUser extends gl.FilteredSearchDropdown {
constructor(droplab, dropdown, input, filter, endpoint, symbol) { constructor(droplab, dropdown, input, filter, endpoint, symbol) {
super(droplab, dropdown, input, filter); super(droplab, dropdown, input, filter);
this.symbol = symbol; this.symbol = symbol;
...@@ -45,8 +44,7 @@ require('./filtered_search_dropdown'); ...@@ -45,8 +44,7 @@ require('./filtered_search_dropdown');
this.droplab this.droplab
.addHook(this.input, this.dropdown, [Ajax, Filter], this.config).init(); .addHook(this.input, this.dropdown, [Ajax, Filter], this.config).init();
} }
} }
window.gl = window.gl || {}; window.gl = window.gl || {};
gl.DropdownNonUser = DropdownNonUser; gl.DropdownNonUser = DropdownNonUser;
})();
...@@ -4,8 +4,7 @@ import AjaxFilter from '~/droplab/plugins/ajax_filter'; ...@@ -4,8 +4,7 @@ import AjaxFilter from '~/droplab/plugins/ajax_filter';
require('./filtered_search_dropdown'); require('./filtered_search_dropdown');
(() => { class DropdownUser extends gl.FilteredSearchDropdown {
class DropdownUser extends gl.FilteredSearchDropdown {
constructor(droplab, dropdown, input, filter) { constructor(droplab, dropdown, input, filter) {
super(droplab, dropdown, input, filter); super(droplab, dropdown, input, filter);
this.config = { this.config = {
...@@ -65,8 +64,7 @@ require('./filtered_search_dropdown'); ...@@ -65,8 +64,7 @@ require('./filtered_search_dropdown');
init() { init() {
this.droplab.addHook(this.input, this.dropdown, [AjaxFilter], this.config).init(); this.droplab.addHook(this.input, this.dropdown, [AjaxFilter], this.config).init();
} }
} }
window.gl = window.gl || {}; window.gl = window.gl || {};
gl.DropdownUser = DropdownUser; gl.DropdownUser = DropdownUser;
})();
import FilteredSearchContainer from './container'; import FilteredSearchContainer from './container';
(() => { class DropdownUtils {
class DropdownUtils {
static getEscapedText(text) { static getEscapedText(text) {
let escapedText = text; let escapedText = text;
const hasSpace = text.indexOf(' ') !== -1; const hasSpace = text.indexOf(' ') !== -1;
...@@ -176,8 +175,7 @@ import FilteredSearchContainer from './container'; ...@@ -176,8 +175,7 @@ import FilteredSearchContainer from './container';
right, right,
}; };
} }
} }
window.gl = window.gl || {}; window.gl = window.gl || {};
gl.DropdownUtils = DropdownUtils; gl.DropdownUtils = DropdownUtils;
})();
(() => { const DATA_DROPDOWN_TRIGGER = 'data-dropdown-trigger';
const DATA_DROPDOWN_TRIGGER = 'data-dropdown-trigger';
class FilteredSearchDropdown { class FilteredSearchDropdown {
constructor(droplab, dropdown, input, filter) { constructor(droplab, dropdown, input, filter) {
this.droplab = droplab; this.droplab = droplab;
this.hookId = input && input.id; this.hookId = input && input.id;
...@@ -104,6 +103,7 @@ ...@@ -104,6 +103,7 @@
} }
} }
<<<<<<< HEAD
resetFilters() { resetFilters() {
const hook = this.getCurrentHook(); const hook = this.getCurrentHook();
...@@ -119,9 +119,22 @@ ...@@ -119,9 +119,22 @@
}); });
hook.list.render(results); hook.list.render(results);
} }
=======
resetFilters() {
const hook = this.getCurrentHook();
if (hook) {
const data = hook.list.data || [];
const results = data.map((o) => {
const updated = o;
updated.droplab_hidden = false;
return updated;
});
hook.list.render(results);
>>>>>>> ce/master
} }
} }
}
window.gl = window.gl || {}; window.gl = window.gl || {};
gl.FilteredSearchDropdown = FilteredSearchDropdown; gl.FilteredSearchDropdown = FilteredSearchDropdown;
})();
import DropLab from '~/droplab/drop_lab'; import DropLab from '~/droplab/drop_lab';
import FilteredSearchContainer from './container'; import FilteredSearchContainer from './container';
<<<<<<< HEAD
(() => { (() => {
class FilteredSearchDropdownManager { class FilteredSearchDropdownManager {
constructor(baseEndpoint = '', page) { constructor(baseEndpoint = '', page) {
...@@ -17,6 +18,20 @@ import FilteredSearchContainer from './container'; ...@@ -17,6 +18,20 @@ import FilteredSearchContainer from './container';
this.setupMapping(); this.setupMapping();
this.cleanupWrapper = this.cleanup.bind(this);
document.addEventListener('beforeunload', this.cleanupWrapper);
=======
class FilteredSearchDropdownManager {
constructor(baseEndpoint = '', page) {
this.container = FilteredSearchContainer.container;
this.baseEndpoint = baseEndpoint.replace(/\/$/, '');
this.tokenizer = gl.FilteredSearchTokenizer;
this.filteredSearchTokenKeys = gl.FilteredSearchTokenKeys;
this.filteredSearchInput = this.container.querySelector('.filtered-search');
this.page = page;
this.setupMapping();
this.cleanupWrapper = this.cleanup.bind(this); this.cleanupWrapper = this.cleanup.bind(this);
document.addEventListener('beforeunload', this.cleanupWrapper); document.addEventListener('beforeunload', this.cleanupWrapper);
} }
...@@ -25,6 +40,7 @@ import FilteredSearchContainer from './container'; ...@@ -25,6 +40,7 @@ import FilteredSearchContainer from './container';
if (this.droplab) { if (this.droplab) {
this.droplab.destroy(); this.droplab.destroy();
this.droplab = null; this.droplab = null;
>>>>>>> ce/master
} }
this.setupMapping(); this.setupMapping();
...@@ -32,6 +48,39 @@ import FilteredSearchContainer from './container'; ...@@ -32,6 +48,39 @@ import FilteredSearchContainer from './container';
document.removeEventListener('beforeunload', this.cleanupWrapper); document.removeEventListener('beforeunload', this.cleanupWrapper);
} }
setupMapping() {
this.mapping = {
author: {
reference: null,
gl: 'DropdownUser',
element: this.container.querySelector('#js-dropdown-author'),
},
assignee: {
reference: null,
gl: 'DropdownUser',
element: this.container.querySelector('#js-dropdown-assignee'),
},
milestone: {
reference: null,
gl: 'DropdownNonUser',
extraArguments: [`${this.baseEndpoint}/milestones.json`, '%'],
element: this.container.querySelector('#js-dropdown-milestone'),
},
label: {
reference: null,
gl: 'DropdownNonUser',
extraArguments: [`${this.baseEndpoint}/labels.json`, '~'],
element: this.container.querySelector('#js-dropdown-label'),
},
hint: {
reference: null,
gl: 'DropdownHint',
element: this.container.querySelector('#js-dropdown-hint'),
},
};
}
<<<<<<< HEAD
setupMapping() { setupMapping() {
this.mapping = { this.mapping = {
author: { author: {
...@@ -70,8 +119,7 @@ import FilteredSearchContainer from './container'; ...@@ -70,8 +119,7 @@ import FilteredSearchContainer from './container';
element: document.querySelector('#js-dropdown-weight'), element: document.querySelector('#js-dropdown-weight'),
}; };
} }
} =======
static addWordToInput(tokenName, tokenValue = '', clicked = false) { static addWordToInput(tokenName, tokenValue = '', clicked = false) {
const input = FilteredSearchContainer.container.querySelector('.filtered-search'); const input = FilteredSearchContainer.container.querySelector('.filtered-search');
...@@ -80,6 +128,7 @@ import FilteredSearchContainer from './container'; ...@@ -80,6 +128,7 @@ import FilteredSearchContainer from './container';
if (clicked) { if (clicked) {
gl.FilteredSearchVisualTokens.moveInputToTheRight(); gl.FilteredSearchVisualTokens.moveInputToTheRight();
>>>>>>> ce/master
} }
} }
...@@ -196,8 +245,7 @@ import FilteredSearchContainer from './container'; ...@@ -196,8 +245,7 @@ import FilteredSearchContainer from './container';
destroyDroplab() { destroyDroplab() {
this.droplab.destroy(); this.droplab.destroy();
} }
} }
window.gl = window.gl || {}; window.gl = window.gl || {};
gl.FilteredSearchDropdownManager = FilteredSearchDropdownManager; gl.FilteredSearchDropdownManager = FilteredSearchDropdownManager;
})();
...@@ -6,6 +6,7 @@ import RecentSearchesStore from './stores/recent_searches_store'; ...@@ -6,6 +6,7 @@ import RecentSearchesStore from './stores/recent_searches_store';
import RecentSearchesService from './services/recent_searches_service'; import RecentSearchesService from './services/recent_searches_service';
import eventHub from './event_hub'; import eventHub from './event_hub';
<<<<<<< HEAD
(() => { (() => {
class FilteredSearchManager { class FilteredSearchManager {
constructor(page) { constructor(page) {
...@@ -44,6 +45,49 @@ import eventHub from './event_hub'; ...@@ -44,6 +45,49 @@ import eventHub from './event_hub';
this.recentSearchesService.save(resultantSearches); this.recentSearchesService.save(resultantSearches);
}); });
if (this.filteredSearchInput) {
this.tokenizer = gl.FilteredSearchTokenizer;
this.dropdownManager = new gl.FilteredSearchDropdownManager(this.filteredSearchInput.getAttribute('data-base-endpoint') || '', page);
this.recentSearchesRoot = new RecentSearchesRoot(
this.recentSearchesStore,
this.recentSearchesService,
document.querySelector('.js-filtered-search-history-dropdown'),
=======
class FilteredSearchManager {
constructor(page) {
this.container = FilteredSearchContainer.container;
this.filteredSearchInput = this.container.querySelector('.filtered-search');
this.filteredSearchInputForm = this.filteredSearchInput.form;
this.clearSearchButton = this.container.querySelector('.clear-search');
this.tokensContainer = this.container.querySelector('.tokens-container');
this.filteredSearchTokenKeys = gl.FilteredSearchTokenKeys;
this.recentSearchesStore = new RecentSearchesStore();
let recentSearchesKey = 'issue-recent-searches';
if (page === 'merge_requests') {
recentSearchesKey = 'merge-request-recent-searches';
}
this.recentSearchesService = new RecentSearchesService(recentSearchesKey);
// Fetch recent searches from localStorage
this.fetchingRecentSearchesPromise = this.recentSearchesService.fetch()
.catch(() => {
// eslint-disable-next-line no-new
new Flash('An error occured while parsing recent searches');
// Gracefully fail to empty array
return [];
})
.then((searches) => {
// Put any searches that may have come in before
// we fetched the saved searches ahead of the already saved ones
const resultantSearches = this.recentSearchesStore.setRecentSearches(
this.recentSearchesStore.state.recentSearches.concat(searches),
>>>>>>> ce/master
);
this.recentSearchesService.save(resultantSearches);
});
if (this.filteredSearchInput) { if (this.filteredSearchInput) {
this.tokenizer = gl.FilteredSearchTokenizer; this.tokenizer = gl.FilteredSearchTokenizer;
this.dropdownManager = new gl.FilteredSearchDropdownManager(this.filteredSearchInput.getAttribute('data-base-endpoint') || '', page); this.dropdownManager = new gl.FilteredSearchDropdownManager(this.filteredSearchInput.getAttribute('data-base-endpoint') || '', page);
...@@ -110,6 +154,14 @@ import eventHub from './event_hub'; ...@@ -110,6 +154,14 @@ import eventHub from './event_hub';
eventHub.$on('recentSearchesItemSelected', this.onrecentSearchesItemSelectedWrapper); eventHub.$on('recentSearchesItemSelected', this.onrecentSearchesItemSelectedWrapper);
} }
<<<<<<< HEAD
if (this.filteredSearchInput.value === '' && lastVisualToken) {
if (this.canEdit && !this.canEdit(lastVisualToken)) return;
this.filteredSearchInput.value = gl.FilteredSearchVisualTokens.getLastTokenPartial();
gl.FilteredSearchVisualTokens.removeLastTokenPartial();
}
=======
unbindEvents() { unbindEvents() {
this.filteredSearchInputForm.removeEventListener('submit', this.handleFormSubmit); this.filteredSearchInputForm.removeEventListener('submit', this.handleFormSubmit);
this.filteredSearchInput.removeEventListener('input', this.setDropdownWrapper); this.filteredSearchInput.removeEventListener('input', this.setDropdownWrapper);
...@@ -136,10 +188,9 @@ import eventHub from './event_hub'; ...@@ -136,10 +188,9 @@ import eventHub from './event_hub';
// 46 = Delete Key // 46 = Delete Key
if (e.keyCode === 8 || e.keyCode === 46) { if (e.keyCode === 8 || e.keyCode === 46) {
const { lastVisualToken } = gl.FilteredSearchVisualTokens.getLastVisualTokenBeforeInput(); const { lastVisualToken } = gl.FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
>>>>>>> ce/master
if (this.filteredSearchInput.value === '' && lastVisualToken) { if (this.filteredSearchInput.value === '' && lastVisualToken) {
if (this.canEdit && !this.canEdit(lastVisualToken)) return;
this.filteredSearchInput.value = gl.FilteredSearchVisualTokens.getLastTokenPartial(); this.filteredSearchInput.value = gl.FilteredSearchVisualTokens.getLastTokenPartial();
gl.FilteredSearchVisualTokens.removeLastTokenPartial(); gl.FilteredSearchVisualTokens.removeLastTokenPartial();
} }
...@@ -225,12 +276,19 @@ import eventHub from './event_hub'; ...@@ -225,12 +276,19 @@ import eventHub from './event_hub';
editToken(e) { editToken(e) {
const token = e.target.closest('.js-visual-token'); const token = e.target.closest('.js-visual-token');
<<<<<<< HEAD
if (this.canEdit && !this.canEdit(token)) return; if (this.canEdit && !this.canEdit(token)) return;
if (token) { if (token) {
gl.FilteredSearchVisualTokens.editToken(token); gl.FilteredSearchVisualTokens.editToken(token);
this.tokenChange(); this.tokenChange();
} }
=======
if (token) {
gl.FilteredSearchVisualTokens.editToken(token);
this.tokenChange();
>>>>>>> ce/master
}
} }
toggleClearSearchButton() { toggleClearSearchButton() {
...@@ -277,6 +335,7 @@ import eventHub from './event_hub'; ...@@ -277,6 +335,7 @@ import eventHub from './event_hub';
const removeElements = []; const removeElements = [];
<<<<<<< HEAD
[].forEach.call(this.tokensContainer.children, (t) => { [].forEach.call(this.tokensContainer.children, (t) => {
if (t.classList.contains('js-visual-token')) { if (t.classList.contains('js-visual-token')) {
if (this.canEdit && !this.canEdit(t)) return; if (this.canEdit && !this.canEdit(t)) return;
...@@ -284,6 +343,13 @@ import eventHub from './event_hub'; ...@@ -284,6 +343,13 @@ import eventHub from './event_hub';
removeElements.push(t); removeElements.push(t);
} }
}); });
=======
[].forEach.call(this.tokensContainer.children, (t) => {
if (t.classList.contains('js-visual-token')) {
removeElements.push(t);
}
});
>>>>>>> ce/master
removeElements.forEach((el) => { removeElements.forEach((el) => {
el.parentElement.removeChild(el); el.parentElement.removeChild(el);
...@@ -497,8 +563,7 @@ import eventHub from './event_hub'; ...@@ -497,8 +563,7 @@ import eventHub from './event_hub';
this.filteredSearchInput.dispatchEvent(new CustomEvent('input')); this.filteredSearchInput.dispatchEvent(new CustomEvent('input'));
this.search(); this.search();
} }
} }
window.gl = window.gl || {}; window.gl = window.gl || {};
gl.FilteredSearchManager = FilteredSearchManager; gl.FilteredSearchManager = FilteredSearchManager;
})();
(() => { const tokenKeys = [{
const tokenKeys = [{
key: 'author', key: 'author',
type: 'string', type: 'string',
param: 'username', param: 'username',
symbol: '@', symbol: '@',
}, { }, {
key: 'assignee', key: 'assignee',
type: 'string', type: 'string',
param: 'username', param: 'username',
symbol: '@', symbol: '@',
}, { }, {
key: 'milestone', key: 'milestone',
type: 'string', type: 'string',
param: 'title', param: 'title',
symbol: '%', symbol: '%',
}, { }, {
key: 'label', key: 'label',
type: 'array', type: 'array',
param: 'name[]', param: 'name[]',
symbol: '~', symbol: '~',
}]; }];
const alternativeTokenKeys = [{ const alternativeTokenKeys = [{
key: 'label', key: 'label',
type: 'string', type: 'string',
param: 'name', param: 'name',
symbol: '~', symbol: '~',
}]; }];
const tokenKeysWithAlternative = tokenKeys.concat(alternativeTokenKeys); const tokenKeysWithAlternative = tokenKeys.concat(alternativeTokenKeys);
const conditions = [{ const conditions = [{
url: 'assignee_id=0', url: 'assignee_id=0',
tokenKey: 'assignee', tokenKey: 'assignee',
value: 'none', value: 'none',
}, { }, {
url: 'milestone_title=No+Milestone', url: 'milestone_title=No+Milestone',
tokenKey: 'milestone', tokenKey: 'milestone',
value: 'none', value: 'none',
}, { }, {
url: 'milestone_title=%23upcoming', url: 'milestone_title=%23upcoming',
tokenKey: 'milestone', tokenKey: 'milestone',
value: 'upcoming', value: 'upcoming',
}, { }, {
url: 'milestone_title=%23started', url: 'milestone_title=%23started',
tokenKey: 'milestone', tokenKey: 'milestone',
value: 'started', value: 'started',
}, { }, {
url: 'label_name[]=No+Label', url: 'label_name[]=No+Label',
tokenKey: 'label', tokenKey: 'label',
value: 'none', value: 'none',
}]; }];
class FilteredSearchTokenKeys { class FilteredSearchTokenKeys {
static get() { static get() {
return tokenKeys; return tokenKeys;
} }
...@@ -93,8 +92,7 @@ ...@@ -93,8 +92,7 @@
return conditions return conditions
.find(condition => condition.tokenKey === key && condition.value === value) || null; .find(condition => condition.tokenKey === key && condition.value === value) || null;
} }
} }
window.gl = window.gl || {}; window.gl = window.gl || {};
gl.FilteredSearchTokenKeys = FilteredSearchTokenKeys; gl.FilteredSearchTokenKeys = FilteredSearchTokenKeys;
})();
require('./filtered_search_token_keys'); require('./filtered_search_token_keys');
(() => { class FilteredSearchTokenizer {
class FilteredSearchTokenizer {
static processTokens(input) { static processTokens(input) {
const allowedKeys = gl.FilteredSearchTokenKeys.get().map(i => i.key); const allowedKeys = gl.FilteredSearchTokenKeys.get().map(i => i.key);
// Regex extracts `(token):(symbol)(value)` // Regex extracts `(token):(symbol)(value)`
...@@ -51,8 +50,7 @@ require('./filtered_search_token_keys'); ...@@ -51,8 +50,7 @@ require('./filtered_search_token_keys');
searchToken, searchToken,
}; };
} }
} }
window.gl = window.gl || {}; window.gl = window.gl || {};
gl.FilteredSearchTokenizer = FilteredSearchTokenizer; gl.FilteredSearchTokenizer = FilteredSearchTokenizer;
})();
...@@ -368,9 +368,9 @@ ...@@ -368,9 +368,9 @@
}); });
}; };
w.gl.utils.setFavicon = (iconName) => { w.gl.utils.setFavicon = (faviconPath) => {
if (faviconEl && iconName) { if (faviconEl && faviconPath) {
faviconEl.setAttribute('href', `/assets/${iconName}.ico`); faviconEl.setAttribute('href', faviconPath);
} }
}; };
...@@ -385,8 +385,8 @@ ...@@ -385,8 +385,8 @@
url: pageUrl, url: pageUrl,
dataType: 'json', dataType: 'json',
success: function(data) { success: function(data) {
if (data && data.icon) { if (data && data.favicon) {
gl.utils.setFavicon(`ci_favicons/${data.icon}`); gl.utils.setFavicon(data.favicon);
} else { } else {
gl.utils.resetFavicon(); gl.utils.resetFavicon();
} }
......
...@@ -165,6 +165,7 @@ import './syntax_highlight'; ...@@ -165,6 +165,7 @@ import './syntax_highlight';
import './task_list'; import './task_list';
import './todos'; import './todos';
import './tree'; import './tree';
import './usage_ping';
import './user'; import './user';
import './user_tabs'; import './user_tabs';
import './username_validator'; import './username_validator';
...@@ -218,6 +219,14 @@ $(function () { ...@@ -218,6 +219,14 @@ $(function () {
} }
}); });
if (bootstrapBreakpoint === 'xs') {
const $rightSidebar = $('aside.right-sidebar, .page-with-sidebar');
$rightSidebar
.removeClass('right-sidebar-expanded')
.addClass('right-sidebar-collapsed');
}
// prevent default action for disabled buttons // prevent default action for disabled buttons
$('.btn').click(function(e) { $('.btn').click(function(e) {
if ($(this).hasClass('disabled')) { if ($(this).hasClass('disabled')) {
......
...@@ -308,8 +308,10 @@ require('./task_list'); ...@@ -308,8 +308,10 @@ require('./task_list');
if (this.isNewNote(note)) { if (this.isNewNote(note)) {
this.note_ids.push(note.id); this.note_ids.push(note.id);
$notesList = $('ul.main-notes-list');
$notesList.append(note.html).syntaxHighlight(); $notesList = window.$('ul.main-notes-list');
Notes.animateAppendNote(note.html, $notesList);
// Update datetime format on the recent note // Update datetime format on the recent note
gl.utils.localTimeAgo($notesList.find("#note_" + note.id + " .js-timeago"), false); gl.utils.localTimeAgo($notesList.find("#note_" + note.id + " .js-timeago"), false);
this.collapseLongCommitList(); this.collapseLongCommitList();
...@@ -348,7 +350,7 @@ require('./task_list'); ...@@ -348,7 +350,7 @@ require('./task_list');
lineType = this.isParallelView() ? form.find('#line_type').val() : 'old'; lineType = this.isParallelView() ? form.find('#line_type').val() : 'old';
diffAvatarContainer = row.prevAll('.line_holder').first().find('.js-avatar-container.' + lineType + '_line'); diffAvatarContainer = row.prevAll('.line_holder').first().find('.js-avatar-container.' + lineType + '_line');
// is this the first note of discussion? // is this the first note of discussion?
discussionContainer = $(".notes[data-discussion-id='" + note.discussion_id + "']"); discussionContainer = window.$(`.notes[data-discussion-id="${note.discussion_id}"]`);
if (!discussionContainer.length) { if (!discussionContainer.length) {
discussionContainer = form.closest('.discussion').find('.notes'); discussionContainer = form.closest('.discussion').find('.notes');
} }
...@@ -370,14 +372,13 @@ require('./task_list'); ...@@ -370,14 +372,13 @@ require('./task_list');
row.find(contentContainerClass + ' .content').append($notes.closest('.content').children()); row.find(contentContainerClass + ' .content').append($notes.closest('.content').children());
} }
} }
// Init discussion on 'Discussion' page if it is merge request page // Init discussion on 'Discussion' page if it is merge request page
if ($('body').attr('data-page').indexOf('projects:merge_request') === 0 || !note.diff_discussion_html) { if (window.$('body').attr('data-page').indexOf('projects:merge_request') === 0 || !note.diff_discussion_html) {
$('ul.main-notes-list').append($(note.discussion_html).renderGFM()); Notes.animateAppendNote(note.discussion_html, window.$('ul.main-notes-list'));
} }
} else { } else {
// append new note to all matching discussions // append new note to all matching discussions
discussionContainer.append($(note.html).renderGFM()); Notes.animateAppendNote(note.html, discussionContainer);
} }
if (typeof gl.diffNotesCompileComponents !== 'undefined' && note.discussion_resolvable) { if (typeof gl.diffNotesCompileComponents !== 'undefined' && note.discussion_resolvable) {
...@@ -1063,6 +1064,13 @@ require('./task_list'); ...@@ -1063,6 +1064,13 @@ require('./task_list');
return $form; return $form;
}; };
Notes.animateAppendNote = function(noteHTML, $notesList) {
const $note = window.$(noteHTML);
$note.addClass('fade-in').renderGFM();
$notesList.append($note);
};
return Notes; return Notes;
})(); })();
}).call(window); }).call(window);
/* global Flash */ /* global Flash */
import canceledSvg from 'icons/_icon_status_canceled_borderless.svg'; import StatusIconEntityMap from '../../ci_status_icons';
import createdSvg from 'icons/_icon_status_created_borderless.svg';
import failedSvg from 'icons/_icon_status_failed_borderless.svg';
import manualSvg from 'icons/_icon_status_manual_borderless.svg';
import pendingSvg from 'icons/_icon_status_pending_borderless.svg';
import runningSvg from 'icons/_icon_status_running_borderless.svg';
import skippedSvg from 'icons/_icon_status_skipped_borderless.svg';
import successSvg from 'icons/_icon_status_success_borderless.svg';
import warningSvg from 'icons/_icon_status_warning_borderless.svg';
export default { export default {
data() { data() {
const svgsDictionary = {
icon_status_canceled: canceledSvg,
icon_status_created: createdSvg,
icon_status_failed: failedSvg,
icon_status_manual: manualSvg,
icon_status_pending: pendingSvg,
icon_status_running: runningSvg,
icon_status_skipped: skippedSvg,
icon_status_success: successSvg,
icon_status_warning: warningSvg,
};
return { return {
builds: '', builds: '',
spinner: '<span class="fa fa-spinner fa-spin"></span>', spinner: '<span class="fa fa-spinner fa-spin"></span>',
svg: svgsDictionary[this.stage.status.icon],
}; };
}, },
...@@ -89,6 +68,9 @@ export default { ...@@ -89,6 +68,9 @@ export default {
triggerButtonClass() { triggerButtonClass() {
return `mini-pipeline-graph-dropdown-toggle has-tooltip js-builds-dropdown-button ci-status-icon-${this.stage.status.group}`; return `mini-pipeline-graph-dropdown-toggle has-tooltip js-builds-dropdown-button ci-status-icon-${this.stage.status.group}`;
}, },
svgHTML() {
return StatusIconEntityMap[this.stage.status.icon];
},
}, },
template: ` template: `
<div> <div>
...@@ -100,7 +82,7 @@ export default { ...@@ -100,7 +82,7 @@ export default {
data-toggle="dropdown" data-toggle="dropdown"
type="button" type="button"
:aria-label="stage.title"> :aria-label="stage.title">
<span v-html="svg" aria-hidden="true"></span> <span v-html="svgHTML" aria-hidden="true"></span>
<i class="fa fa-caret-down" aria-hidden="true"></i> <i class="fa fa-caret-down" aria-hidden="true"></i>
</button> </button>
<ul class="dropdown-menu mini-pipeline-graph-dropdown-menu js-builds-dropdown-container"> <ul class="dropdown-menu mini-pipeline-graph-dropdown-menu js-builds-dropdown-container">
......
function UsagePing() {
const usageDataUrl = $('.usage-data').data('endpoint');
$.ajax({
type: 'GET',
url: usageDataUrl,
dataType: 'html',
success(html) {
$('.usage-data').html(html);
},
});
}
window.gl = window.gl || {};
window.gl.UsagePing = UsagePing;
...@@ -145,3 +145,17 @@ a { ...@@ -145,3 +145,17 @@ a {
.dropdown-menu-nav a { .dropdown-menu-nav a {
transition: none; transition: none;
} }
@keyframes fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.fade-in {
animation: fadeIn $fade-in-duration 1;
}
...@@ -40,6 +40,10 @@ ...@@ -40,6 +40,10 @@
line-height: 24px; line-height: 24px;
} }
.bold {
font-weight: 600;
}
.tab-content { .tab-content {
overflow: visible; overflow: visible;
} }
......
...@@ -564,3 +564,7 @@ ...@@ -564,3 +564,7 @@
color: $gl-text-color-secondary; color: $gl-text-color-secondary;
} }
} }
.droplab-item-ignore {
pointer-events: none;
}
...@@ -331,6 +331,14 @@ header { ...@@ -331,6 +331,14 @@ header {
.dropdown-menu-nav { .dropdown-menu-nav {
min-width: 140px; min-width: 140px;
margin-top: -5px; margin-top: -5px;
.current-user {
padding: 5px 18px;
.user-name {
display: block;
}
}
} }
} }
......
...@@ -460,6 +460,11 @@ $label-inverse-bg: #333; ...@@ -460,6 +460,11 @@ $label-inverse-bg: #333;
$label-remove-border: rgba(0, 0, 0, .1); $label-remove-border: rgba(0, 0, 0, .1);
$label-border-radius: 100px; $label-border-radius: 100px;
/*
* Animation
*/
$fade-in-duration: 200ms;
/* /*
* Lint * Lint
*/ */
......
...@@ -210,10 +210,6 @@ ...@@ -210,10 +210,6 @@
} }
} }
.bold {
font-weight: 600;
}
.light { .light {
font-weight: normal; font-weight: normal;
} }
......
...@@ -289,8 +289,12 @@ table.u2f-registrations { ...@@ -289,8 +289,12 @@ table.u2f-registrations {
margin: 0 auto; margin: 0 auto;
.bordered-box { .bordered-box {
border: 1px solid $border-color; border: 1px solid $blue-300;
border-radius: $border-radius-default; border-radius: $border-radius-default;
background-color: $blue-25;
position: relative;
display: flex;
justify-content: center;
} }
.landing { .landing {
...@@ -298,28 +302,59 @@ table.u2f-registrations { ...@@ -298,28 +302,59 @@ table.u2f-registrations {
margin-bottom: $gl-padding; margin-bottom: $gl-padding;
.close { .close {
margin-right: 20px; position: absolute;
} right: 20px;
opacity: 1;
.dismiss-icon { .dismiss-icon {
float: right; float: right;
cursor: pointer; cursor: pointer;
color: $cycle-analytics-dismiss-icon-color; color: $blue-300;
}
&:hover {
background-color: transparent;
border: 0;
.dismiss-icon {
color: $blue-400;
}
}
} }
.svg-container { .svg-container {
text-align: center; margin-right: 30px;
display: inline-block;
svg { svg {
width: 136px; height: 110px;
height: 136px; vertical-align: top;
} }
} }
.user-callout-copy {
display: inline-block;
vertical-align: top;
}
} }
@media(max-width: $screen-xs-max) { @media(max-width: $screen-xs-max) {
.inner-content { text-align: center;
padding-left: 30px;
.bordered-box {
display: block;
}
.landing {
.svg-container,
.user-callout-copy {
margin: 0;
display: block;
svg {
height: 75px;
}
}
} }
} }
} }
...@@ -604,6 +604,10 @@ pre.light-well { ...@@ -604,6 +604,10 @@ pre.light-well {
.avatar-container { .avatar-container {
align-self: flex-start; align-self: flex-start;
> a {
width: 100%;
}
} }
.project-details { .project-details {
......
...@@ -112,4 +112,8 @@ class Projects::GitHttpController < Projects::GitHttpClientController ...@@ -112,4 +112,8 @@ class Projects::GitHttpController < Projects::GitHttpClientController
def access_klass def access_klass
@access_klass ||= wiki? ? Gitlab::GitAccessWiki : Gitlab::GitAccess @access_klass ||= wiki? ? Gitlab::GitAccessWiki : Gitlab::GitAccess
end end
def log_user_activity
Users::ActivityService.new(user, 'pull').execute
end
end end
...@@ -64,6 +64,14 @@ module SortingHelper ...@@ -64,6 +64,14 @@ module SortingHelper
} }
end end
def branches_sort_options_hash
{
sort_value_name => sort_title_name,
sort_value_recently_updated => sort_title_recently_updated,
sort_value_oldest_updated => sort_title_oldest_updated
}
end
def sort_title_priority def sort_title_priority
'Priority' 'Priority'
end end
......
...@@ -259,6 +259,7 @@ class ApplicationSetting < ActiveRecord::Base ...@@ -259,6 +259,7 @@ class ApplicationSetting < ActiveRecord::Base
user_default_external: false, user_default_external: false,
polling_interval_multiplier: 1, polling_interval_multiplier: 1,
usage_ping_enabled: true usage_ping_enabled: true
<<<<<<< HEAD
} }
end end
...@@ -269,6 +270,8 @@ class ApplicationSetting < ActiveRecord::Base ...@@ -269,6 +270,8 @@ class ApplicationSetting < ActiveRecord::Base
elasticsearch_aws_region: ENV['ELASTIC_REGION'] || 'us-east-1', elasticsearch_aws_region: ENV['ELASTIC_REGION'] || 'us-east-1',
minimum_mirror_sync_time: Gitlab::Mirror::FIFTEEN, minimum_mirror_sync_time: Gitlab::Mirror::FIFTEEN,
repository_size_limit: 0 repository_size_limit: 0
=======
>>>>>>> ce/master
} }
end end
......
...@@ -23,7 +23,7 @@ module Issuable ...@@ -23,7 +23,7 @@ module Issuable
included do included do
cache_markdown_field :title, pipeline: :single_line cache_markdown_field :title, pipeline: :single_line
cache_markdown_field :description cache_markdown_field :description, issuable_state_filter_enabled: true
belongs_to :author, class_name: "User" belongs_to :author, class_name: "User"
belongs_to :assignee, class_name: "User" belongs_to :assignee, class_name: "User"
......
...@@ -7,7 +7,11 @@ class Identity < ActiveRecord::Base ...@@ -7,7 +7,11 @@ class Identity < ActiveRecord::Base
validates :extern_uid, allow_blank: true, uniqueness: { scope: :provider } validates :extern_uid, allow_blank: true, uniqueness: { scope: :provider }
validates :user_id, uniqueness: { scope: :provider } validates :user_id, uniqueness: { scope: :provider }
<<<<<<< HEAD
scope :with_provider, ->(provider) { where(provider: provider) } scope :with_provider, ->(provider) { where(provider: provider) }
=======
scope :with_extern_uid, ->(provider, extern_uid) { where(extern_uid: extern_uid, provider: provider) }
>>>>>>> ce/master
def ldap? def ldap?
provider.starts_with?('ldap') provider.starts_with?('ldap')
......
...@@ -17,7 +17,7 @@ class Note < ActiveRecord::Base ...@@ -17,7 +17,7 @@ class Note < ActiveRecord::Base
ignore_column :original_discussion_id ignore_column :original_discussion_id
cache_markdown_field :note, pipeline: :note cache_markdown_field :note, pipeline: :note, issuable_state_filter_enabled: true
# Attribute containing rendered and redacted Markdown as generated by # Attribute containing rendered and redacted Markdown as generated by
# Banzai::ObjectRenderer. # Banzai::ObjectRenderer.
......
...@@ -22,7 +22,7 @@ class ChatNotificationService < Service ...@@ -22,7 +22,7 @@ class ChatNotificationService < Service
end end
def can_test? def can_test?
valid? super && valid?
end end
def self.supported_events def self.supported_events
......
class StatusEntity < Grape::Entity class StatusEntity < Grape::Entity
include RequestAwareEntity include RequestAwareEntity
expose :icon, :favicon, :text, :label, :group expose :icon, :text, :label, :group
expose :has_details?, as: :has_details expose :has_details?, as: :has_details
expose :details_path expose :details_path
expose :favicon do |status|
ActionController::Base.helpers.image_path(File.join('ci_favicons', "#{status.favicon}.ico"))
end
end end
...@@ -37,7 +37,10 @@ module Commits ...@@ -37,7 +37,10 @@ module Commits
def validate! def validate!
validate_permissions! validate_permissions!
<<<<<<< HEAD
validate_repository_size! validate_repository_size!
=======
>>>>>>> ce/master
validate_on_branch! validate_on_branch!
validate_branch_existance! validate_branch_existance!
...@@ -52,12 +55,15 @@ module Commits ...@@ -52,12 +55,15 @@ module Commits
end end
end end
<<<<<<< HEAD
def validate_repository_size! def validate_repository_size!
if project.above_size_limit? if project.above_size_limit?
raise_error(Gitlab::RepositorySizeError.new(project).commit_error) raise_error(Gitlab::RepositorySizeError.new(project).commit_error)
end end
end end
=======
>>>>>>> ce/master
def validate_on_branch! def validate_on_branch!
if !@start_project.empty_repo? && !@start_project.repository.branch_exists?(@start_branch) if !@start_project.empty_repo? && !@start_project.repository.branch_exists?(@start_branch)
raise_error('You can only create or edit files when you are on a branch') raise_error('You can only create or edit files when you are on a branch')
......
...@@ -8,9 +8,20 @@ class DeleteMergedBranchesService < BaseService ...@@ -8,9 +8,20 @@ class DeleteMergedBranchesService < BaseService
branches = project.repository.branch_names branches = project.repository.branch_names
branches = branches.select { |branch| project.repository.merged_to_root_ref?(branch) } branches = branches.select { |branch| project.repository.merged_to_root_ref?(branch) }
# Prevent deletion of branches relevant to open merge requests
branches -= merge_request_branch_names
branches.each do |branch| branches.each do |branch|
DeleteBranchService.new(project, current_user).execute(branch) DeleteBranchService.new(project, current_user).execute(branch)
end end
end end
private
def merge_request_branch_names
# reorder(nil) is necessary for SELECT DISTINCT because default scope adds an ORDER BY
source_names = project.origin_merge_requests.opened.reorder(nil).uniq.pluck(:source_branch)
target_names = project.merge_requests.opened.reorder(nil).uniq.pluck(:target_branch)
(source_names + target_names).uniq
end
end end
...@@ -9,6 +9,7 @@ module Search ...@@ -9,6 +9,7 @@ module Search
end end
def execute def execute
<<<<<<< HEAD
if current_application_settings.elasticsearch_search? if current_application_settings.elasticsearch_search?
Gitlab::Elastic::SearchResults.new(current_user, params[:search], elastic_projects, elastic_global) Gitlab::Elastic::SearchResults.new(current_user, params[:search], elastic_projects, elastic_global)
else else
...@@ -33,6 +34,13 @@ module Search ...@@ -33,6 +34,13 @@ module Search
def elastic_global def elastic_global
true true
=======
Gitlab::SearchResults.new(current_user, projects, params[:search])
>>>>>>> ce/master
end
def projects
@projects ||= ProjectsFinder.new(current_user: current_user).execute
end end
def scope def scope
......
...@@ -14,6 +14,7 @@ module Search ...@@ -14,6 +14,7 @@ module Search
@projects = super.inside_path(group.full_path) @projects = super.inside_path(group.full_path)
end end
<<<<<<< HEAD
def elastic_projects def elastic_projects
@elastic_projects ||= projects.pluck(:id) @elastic_projects ||= projects.pluck(:id)
...@@ -22,5 +23,7 @@ module Search ...@@ -22,5 +23,7 @@ module Search
def elastic_global def elastic_global
false false
end end
=======
>>>>>>> ce/master
end end
end end
...@@ -14,7 +14,11 @@ module Users ...@@ -14,7 +14,11 @@ module Users
private private
def record_activity def record_activity
<<<<<<< HEAD
Gitlab::UserActivities.record(@author.id) unless Gitlab::Geo.secondary? Gitlab::UserActivities.record(@author.id) unless Gitlab::Geo.secondary?
=======
Gitlab::UserActivities.record(@author.id)
>>>>>>> ce/master
Rails.logger.debug("Recorded activity: #{@activity} for User ID: #{@author.id} (username: #{@author.username}") Rails.logger.debug("Recorded activity: #{@activity} for User ID: #{@author.id} (username: #{@author.username}")
end end
......
...@@ -515,11 +515,20 @@ ...@@ -515,11 +515,20 @@
= f.check_box :usage_ping_enabled = f.check_box :usage_ping_enabled
Usage ping enabled Usage ping enabled
= link_to icon('question-circle'), help_page_path("user/admin_area/settings/usage_statistics", anchor: "usage-data") = link_to icon('question-circle'), help_page_path("user/admin_area/settings/usage_statistics", anchor: "usage-data")
<<<<<<< HEAD
.container .container
.help-block .help-block
Every week GitLab will report license usage back to GitLab, Inc. Every week GitLab will report license usage back to GitLab, Inc.
Disable this option if you do not want this to occur. This is the JSON payload that will be sent: Disable this option if you do not want this to occur. This is the JSON payload that will be sent:
%pre.usage-data.js-syntax-highlight.code.highlight{ "data-endpoint" => usage_data_admin_application_settings_path(format: :html) } %pre.usage-data.js-syntax-highlight.code.highlight{ "data-endpoint" => usage_data_admin_application_settings_path(format: :html) }
=======
.help-block
Every week GitLab will report license usage back to GitLab, Inc.
Disable this option if you do not want this to occur. To see the
JSON payload that will be sent, visit the
= succeed '.' do
= link_to "Cohorts page", admin_cohorts_path(anchor: 'usage-ping')
>>>>>>> ce/master
%fieldset %fieldset
%legend Email %legend Email
......
<<<<<<< HEAD
%h2 Usage ping %h2 Usage ping
=======
%h2#usage-ping Usage ping
>>>>>>> ce/master
.bs-callout.clearfix .bs-callout.clearfix
%p %p
......
...@@ -79,6 +79,11 @@ ...@@ -79,6 +79,11 @@
= icon('caret-down') = icon('caret-down')
.dropdown-menu-nav.dropdown-menu-align-right .dropdown-menu-nav.dropdown-menu-align-right
%ul %ul
%li.current-user
.user-name.bold
= current_user.name
@#{current_user.username}
%li.divider
%li %li
= link_to "Profile", current_user, class: 'profile-link', aria: { label: "Profile" }, data: { user: current_user.username } = link_to "Profile", current_user, class: 'profile-link', aria: { label: "Profile" }, data: { user: current_user.username }
%li %li
......
...@@ -11,13 +11,17 @@ ...@@ -11,13 +11,17 @@
Project Project
- if project_nav_tab? :files - if project_nav_tab? :files
<<<<<<< HEAD
= nav_link(controller: %w(tree blob blame edit_tree new_tree find_file commit commits compare repositories tags branches releases graphs network path_locks)) do = nav_link(controller: %w(tree blob blame edit_tree new_tree find_file commit commits compare repositories tags branches releases graphs network path_locks)) do
=======
= nav_link(controller: %w(tree blob blame edit_tree new_tree find_file commit commits compare projects/repositories tags branches releases graphs network)) do
>>>>>>> ce/master
= link_to project_files_path(@project), title: 'Repository', class: 'shortcuts-tree' do = link_to project_files_path(@project), title: 'Repository', class: 'shortcuts-tree' do
%span %span
Repository Repository
- if project_nav_tab? :container_registry - if project_nav_tab? :container_registry
= nav_link(controller: %w(container_registry)) do = nav_link(controller: %w[projects/registry/repositories]) do
= link_to project_container_registry_path(@project), title: 'Container Registry', class: 'shortcuts-container-registry' do = link_to project_container_registry_path(@project), title: 'Container Registry', class: 'shortcuts-container-registry' do
%span %span
Registry Registry
......
...@@ -15,16 +15,14 @@ ...@@ -15,16 +15,14 @@
.dropdown.inline> .dropdown.inline>
%button.dropdown-menu-toggle{ type: 'button', 'data-toggle' => 'dropdown' } %button.dropdown-menu-toggle{ type: 'button', 'data-toggle' => 'dropdown' }
%span.light %span.light
= projects_sort_options_hash[@sort] = branches_sort_options_hash[@sort]
= icon('chevron-down') = icon('chevron-down')
%ul.dropdown-menu.dropdown-menu-align-right %ul.dropdown-menu.dropdown-menu-align-right.dropdown-menu-selectable
%li.dropdown-header
Sort by
- branches_sort_options_hash.each do |value, title|
%li %li
= link_to filter_branches_path(sort: sort_value_name) do = link_to title, filter_branches_path(sort: value), class: ("is-active" if @sort == value)
= sort_title_name
= link_to filter_branches_path(sort: sort_value_recently_updated) do
= sort_title_recently_updated
= link_to filter_branches_path(sort: sort_value_oldest_updated) do
= sort_title_oldest_updated
- if can? current_user, :push_code, @project - if can? current_user, :push_code, @project
= link_to namespace_project_merged_branches_path(@project.namespace, @project), class: 'btn btn-inverted btn-remove has-tooltip', title: "Delete all branches that are merged into '#{@project.repository.root_ref}'", method: :delete, data: { confirm: "Deleting the merged branches cannot be undone. Are you sure?", container: 'body' } do = link_to namespace_project_merged_branches_path(@project.namespace, @project), class: 'btn btn-inverted btn-remove has-tooltip', title: "Delete all branches that are merged into '#{@project.repository.root_ref}'", method: :delete, data: { confirm: "Deleting the merged branches cannot be undone. Are you sure?", container: 'body' } do
......
...@@ -13,9 +13,6 @@ ...@@ -13,9 +13,6 @@
Environment: Environment:
= link_to @environment.name, environment_path(@environment) = link_to @environment.name, environment_path(@environment)
.col-sm-6
.nav-controls
= render 'projects/deployments/actions', deployment: @environment.last_deployment
.prometheus-state .prometheus-state
.js-getting-started.hidden .js-getting-started.hidden
.row .row
......
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
-# This tab is always loaded via AJAX -# This tab is always loaded via AJAX
- if @pipelines.any? - if @pipelines.any?
#pipelines.pipelines.tab-pane #pipelines.pipelines.tab-pane
= render 'projects/merge_requests/show/pipelines', endpoint: url_for(params.merge(format: :json)) = render 'projects/merge_requests/show/pipelines', endpoint: url_for(params.merge(format: :json)), disable_initialization: true
.mr-loading-status .mr-loading-status
= spinner = spinner
......
- endpoint_path = local_assigns[:endpoint] || pipelines_namespace_project_merge_request_path(@project.namespace, @project, @merge_request, format: :json) - endpoint_path = local_assigns[:endpoint] || pipelines_namespace_project_merge_request_path(@project.namespace, @project, @merge_request, format: :json)
- disable_initialization = local_assigns.fetch(:disable_initialization, false)
= render 'projects/commit/pipelines_list', endpoint: endpoint_path = render 'projects/commit/pipelines_list', endpoint: endpoint_path, disable_initialization: disable_initialization
...@@ -27,8 +27,11 @@ ...@@ -27,8 +27,11 @@
= render 'projects/merge_requests/widget/open/conflicts' = render 'projects/merge_requests/widget/open/conflicts'
- elsif @merge_request.work_in_progress? - elsif @merge_request.work_in_progress?
= render 'projects/merge_requests/widget/open/wip' = render 'projects/merge_requests/widget/open/wip'
<<<<<<< HEAD
- elsif @merge_request.should_be_rebased? - elsif @merge_request.should_be_rebased?
= render 'projects/merge_requests/widget/open/rebase' = render 'projects/merge_requests/widget/open/rebase'
=======
>>>>>>> ce/master
- elsif @merge_request.merge_when_pipeline_succeeds? && @merge_request.merge_error.present? - elsif @merge_request.merge_when_pipeline_succeeds? && @merge_request.merge_error.present?
= render 'projects/merge_requests/widget/open/error' = render 'projects/merge_requests/widget/open/error'
- elsif @merge_request.merge_when_pipeline_succeeds? - elsif @merge_request.merge_when_pipeline_succeeds?
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
%p %p
Add a general comment to this #{noteable_name}. Add a general comment to this #{noteable_name}.
%li.divider %li.divider.droplab-item-ignore
%li#discussion{ data: { value: 'DiscussionNote', 'submit-text' => 'Start discussion', 'close-text' => "Start discussion & close #{noteable_name}", 'reopen-text' => "Start discussion & reopen #{noteable_name}" } } %li#discussion{ data: { value: 'DiscussionNote', 'submit-text' => 'Start discussion', 'close-text' => "Start discussion & close #{noteable_name}", 'reopen-text' => "Start discussion & reopen #{noteable_name}" } }
%a{ href: '#' } %a{ href: '#' }
......
...@@ -3,12 +3,11 @@ ...@@ -3,12 +3,11 @@
%button.btn.btn-default.close.js-close-callout{ type: 'button', %button.btn.btn-default.close.js-close-callout{ type: 'button',
'aria-label' => 'Dismiss customize experience box' } 'aria-label' => 'Dismiss customize experience box' }
= icon('times', class: 'dismiss-icon', 'aria-hidden' => 'true') = icon('times', class: 'dismiss-icon', 'aria-hidden' => 'true')
.row .svg-container
.col-sm-3.col-xs-12.svg-container
= custom_icon('icon_customization') = custom_icon('icon_customization')
.col-sm-8.col-xs-12.inner-content .user-callout-copy
%h4 %h4
Customize your experience Customize your experience
%p %p
Change syntax themes, default project pages, and more in preferences. Change syntax themes, default project pages, and more in preferences.
= link_to 'Check it out', profile_preferences_path, class: 'btn btn-default js-close-callout' = link_to 'Check it out', profile_preferences_path, class: 'btn btn-primary js-close-callout'
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
= visibility_level_icon(group.visibility_level, fw: false) = visibility_level_icon(group.visibility_level, fw: false)
.avatar-container.s40 .avatar-container.s40
= link_to group do
= image_tag group_icon(group), class: "avatar s40 hidden-xs" = image_tag group_icon(group), class: "avatar s40 hidden-xs"
.title .title
= link_to group_name, group, class: 'group-name' = link_to group_name, group, class: 'group-name'
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
= cache(cache_key) do = cache(cache_key) do
- if avatar - if avatar
.avatar-container.s40 .avatar-container.s40
= link_to project_path(project), class: dom_class(project) do
- if use_creator_avatar - if use_creator_avatar
= image_tag avatar_icon(project.creator.email, 40), class: "avatar s40", alt:'' = image_tag avatar_icon(project.creator.email, 40), class: "avatar s40", alt:''
- else - else
......
...@@ -3,8 +3,11 @@ class ScheduleUpdateUserActivityWorker ...@@ -3,8 +3,11 @@ class ScheduleUpdateUserActivityWorker
include CronjobQueue include CronjobQueue
def perform(batch_size = 500) def perform(batch_size = 500)
<<<<<<< HEAD
return if Gitlab::Geo.secondary? return if Gitlab::Geo.secondary?
=======
>>>>>>> ce/master
Gitlab::UserActivities.new.each_slice(batch_size) do |batch| Gitlab::UserActivities.new.each_slice(batch_size) do |batch|
UpdateUserActivityWorker.perform_async(Hash[batch]) UpdateUserActivityWorker.perform_async(Hash[batch])
end end
......
...@@ -2,6 +2,8 @@ class SystemHookWorker ...@@ -2,6 +2,8 @@ class SystemHookWorker
include Sidekiq::Worker include Sidekiq::Worker
include DedicatedSidekiqQueue include DedicatedSidekiqQueue
sidekiq_options retry: 4
def perform(hook_id, data, hook_name) def perform(hook_id, data, hook_name)
SystemHook.find(hook_id).execute(data, hook_name) SystemHook.find(hook_id).execute(data, hook_name)
end end
......
...@@ -3,8 +3,11 @@ class UpdateUserActivityWorker ...@@ -3,8 +3,11 @@ class UpdateUserActivityWorker
include DedicatedSidekiqQueue include DedicatedSidekiqQueue
def perform(pairs) def perform(pairs)
<<<<<<< HEAD
return if Gitlab::Geo.secondary? return if Gitlab::Geo.secondary?
=======
>>>>>>> ce/master
pairs = cast_data(pairs) pairs = cast_data(pairs)
ids = pairs.keys ids = pairs.keys
conditions = 'WHEN id = ? THEN ? ' * ids.length conditions = 'WHEN id = ? THEN ? ' * ids.length
......
---
title: 29595 Update callout design
merge_request:
author:
---
title: Remove pipeline controls for last deployment from Environment monitoring page
merge_request: 10769
author:
---
title: Added quick-update (fade-in) animation to newly rendered notes
merge_request: 10623
author:
---
title: Added profile name to user dropdown
merge_request:
author:
---
title: Disable test settings on chat notification services when repository is empty
merge_request: 10759
author:
---
title: Display custom hook error messages when automatic merge is enabled
merge_request:
author:
---
title: Removed target blank from the metrics action inside the environments list
merge_request: 10726
author:
---
title: Removed orphaned notification settings without a namespace
merge_request:
author:
---
title: Fixed group milestone date dropdowns not opening
merge_request:
author:
---
title: Add retry to system hook worker
merge_request: 10801
author:
---
title: Fix PlantUML integration in GFM
merge_request: 10651
author:
---
title: Implement search by extern_uid in Users API
merge_request: 10509
author: Robin Bobbitt
---
title: Set the issuable sidebar to remain closed for mobile devices
merge_request:
author:
---
title: Add unique index for notes_id to system note metadata table
merge_request:
author:
---
title: Don't delete a branch involved in an open merge request in "Delete all merged
branches" service
merge_request:
author:
---
title: Add usage ping to CE
merge_request:
author:
...@@ -246,8 +246,8 @@ Settings.gitlab['email_from'] ||= ENV['GITLAB_EMAIL_FROM'] || "gitlab@#{Settings ...@@ -246,8 +246,8 @@ Settings.gitlab['email_from'] ||= ENV['GITLAB_EMAIL_FROM'] || "gitlab@#{Settings
Settings.gitlab['email_display_name'] ||= ENV['GITLAB_EMAIL_DISPLAY_NAME'] || 'GitLab' Settings.gitlab['email_display_name'] ||= ENV['GITLAB_EMAIL_DISPLAY_NAME'] || 'GitLab'
Settings.gitlab['email_reply_to'] ||= ENV['GITLAB_EMAIL_REPLY_TO'] || "noreply@#{Settings.gitlab.host}" Settings.gitlab['email_reply_to'] ||= ENV['GITLAB_EMAIL_REPLY_TO'] || "noreply@#{Settings.gitlab.host}"
Settings.gitlab['email_subject_suffix'] ||= ENV['GITLAB_EMAIL_SUBJECT_SUFFIX'] || "" Settings.gitlab['email_subject_suffix'] ||= ENV['GITLAB_EMAIL_SUBJECT_SUFFIX'] || ""
Settings.gitlab['base_url'] ||= Settings.send(:build_base_gitlab_url) Settings.gitlab['base_url'] ||= Settings.__send__(:build_base_gitlab_url)
Settings.gitlab['url'] ||= Settings.send(:build_gitlab_url) Settings.gitlab['url'] ||= Settings.__send__(:build_gitlab_url)
Settings.gitlab['user'] ||= 'git' Settings.gitlab['user'] ||= 'git'
Settings.gitlab['user_home'] ||= begin Settings.gitlab['user_home'] ||= begin
Etc.getpwnam(Settings.gitlab['user']).dir Etc.getpwnam(Settings.gitlab['user']).dir
...@@ -257,7 +257,7 @@ end ...@@ -257,7 +257,7 @@ end
Settings.gitlab['time_zone'] ||= nil Settings.gitlab['time_zone'] ||= nil
Settings.gitlab['signup_enabled'] ||= true if Settings.gitlab['signup_enabled'].nil? Settings.gitlab['signup_enabled'] ||= true if Settings.gitlab['signup_enabled'].nil?
Settings.gitlab['signin_enabled'] ||= true if Settings.gitlab['signin_enabled'].nil? Settings.gitlab['signin_enabled'] ||= true if Settings.gitlab['signin_enabled'].nil?
Settings.gitlab['restricted_visibility_levels'] = Settings.send(:verify_constant_array, Gitlab::VisibilityLevel, Settings.gitlab['restricted_visibility_levels'], []) Settings.gitlab['restricted_visibility_levels'] = Settings.__send__(:verify_constant_array, Gitlab::VisibilityLevel, Settings.gitlab['restricted_visibility_levels'], [])
Settings.gitlab['username_changing_enabled'] = true if Settings.gitlab['username_changing_enabled'].nil? Settings.gitlab['username_changing_enabled'] = true if Settings.gitlab['username_changing_enabled'].nil?
Settings.gitlab['issue_closing_pattern'] = '((?:[Cc]los(?:e[sd]?|ing)|[Ff]ix(?:e[sd]|ing)?|[Rr]esolv(?:e[sd]?|ing))(:?) +(?:(?:issues? +)?%{issue_ref}(?:(?:, *| +and +)?)|([A-Z][A-Z0-9_]+-\d+))+)' if Settings.gitlab['issue_closing_pattern'].nil? Settings.gitlab['issue_closing_pattern'] = '((?:[Cc]los(?:e[sd]?|ing)|[Ff]ix(?:e[sd]|ing)?|[Rr]esolv(?:e[sd]?|ing))(:?) +(?:(?:issues? +)?%{issue_ref}(?:(?:, *| +and +)?)|([A-Z][A-Z0-9_]+-\d+))+)' if Settings.gitlab['issue_closing_pattern'].nil?
Settings.gitlab['default_projects_features'] ||= {} Settings.gitlab['default_projects_features'] ||= {}
...@@ -270,7 +270,7 @@ Settings.gitlab.default_projects_features['wiki'] = true if Settin ...@@ -270,7 +270,7 @@ Settings.gitlab.default_projects_features['wiki'] = true if Settin
Settings.gitlab.default_projects_features['snippets'] = true if Settings.gitlab.default_projects_features['snippets'].nil? Settings.gitlab.default_projects_features['snippets'] = true if Settings.gitlab.default_projects_features['snippets'].nil?
Settings.gitlab.default_projects_features['builds'] = true if Settings.gitlab.default_projects_features['builds'].nil? Settings.gitlab.default_projects_features['builds'] = true if Settings.gitlab.default_projects_features['builds'].nil?
Settings.gitlab.default_projects_features['container_registry'] = true if Settings.gitlab.default_projects_features['container_registry'].nil? Settings.gitlab.default_projects_features['container_registry'] = true if Settings.gitlab.default_projects_features['container_registry'].nil?
Settings.gitlab.default_projects_features['visibility_level'] = Settings.send(:verify_constant, Gitlab::VisibilityLevel, Settings.gitlab.default_projects_features['visibility_level'], Gitlab::VisibilityLevel::PRIVATE) Settings.gitlab.default_projects_features['visibility_level'] = Settings.__send__(:verify_constant, Gitlab::VisibilityLevel, Settings.gitlab.default_projects_features['visibility_level'], Gitlab::VisibilityLevel::PRIVATE)
Settings.gitlab['domain_whitelist'] ||= [] Settings.gitlab['domain_whitelist'] ||= []
Settings.gitlab['import_sources'] ||= %w[github bitbucket gitlab google_code fogbugz git gitlab_project gitea] Settings.gitlab['import_sources'] ||= %w[github bitbucket gitlab google_code fogbugz git gitlab_project gitea]
Settings.gitlab['trusted_proxies'] ||= [] Settings.gitlab['trusted_proxies'] ||= []
...@@ -291,7 +291,7 @@ Settings.gitlab_ci['shared_runners_enabled'] = true if Settings.gitlab_ci['share ...@@ -291,7 +291,7 @@ Settings.gitlab_ci['shared_runners_enabled'] = true if Settings.gitlab_ci['share
Settings.gitlab_ci['all_broken_builds'] = true if Settings.gitlab_ci['all_broken_builds'].nil? Settings.gitlab_ci['all_broken_builds'] = true if Settings.gitlab_ci['all_broken_builds'].nil?
Settings.gitlab_ci['add_pusher'] = false if Settings.gitlab_ci['add_pusher'].nil? Settings.gitlab_ci['add_pusher'] = false if Settings.gitlab_ci['add_pusher'].nil?
Settings.gitlab_ci['builds_path'] = Settings.absolute(Settings.gitlab_ci['builds_path'] || "builds/") Settings.gitlab_ci['builds_path'] = Settings.absolute(Settings.gitlab_ci['builds_path'] || "builds/")
Settings.gitlab_ci['url'] ||= Settings.send(:build_gitlab_ci_url) Settings.gitlab_ci['url'] ||= Settings.__send__(:build_gitlab_ci_url)
# #
# Reply by email # Reply by email
...@@ -330,7 +330,7 @@ Settings.pages['https'] = false if Settings.pages['https'].nil? ...@@ -330,7 +330,7 @@ Settings.pages['https'] = false if Settings.pages['https'].nil?
Settings.pages['host'] ||= "example.com" Settings.pages['host'] ||= "example.com"
Settings.pages['port'] ||= Settings.pages.https ? 443 : 80 Settings.pages['port'] ||= Settings.pages.https ? 443 : 80
Settings.pages['protocol'] ||= Settings.pages.https ? "https" : "http" Settings.pages['protocol'] ||= Settings.pages.https ? "https" : "http"
Settings.pages['url'] ||= Settings.send(:build_pages_url) Settings.pages['url'] ||= Settings.__send__(:build_pages_url)
Settings.pages['external_http'] ||= false unless Settings.pages['external_http'].present? Settings.pages['external_http'] ||= false unless Settings.pages['external_http'].present?
Settings.pages['external_https'] ||= false unless Settings.pages['external_https'].present? Settings.pages['external_https'] ||= false unless Settings.pages['external_https'].present?
...@@ -430,6 +430,14 @@ Settings.cron_jobs['remove_unreferenced_lfs_objects_worker']['job_class'] = 'Rem ...@@ -430,6 +430,14 @@ Settings.cron_jobs['remove_unreferenced_lfs_objects_worker']['job_class'] = 'Rem
Settings.cron_jobs['stuck_import_jobs_worker'] ||= Settingslogic.new({}) Settings.cron_jobs['stuck_import_jobs_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['stuck_import_jobs_worker']['cron'] ||= '15 * * * *' Settings.cron_jobs['stuck_import_jobs_worker']['cron'] ||= '15 * * * *'
Settings.cron_jobs['stuck_import_jobs_worker']['job_class'] = 'StuckImportJobsWorker' Settings.cron_jobs['stuck_import_jobs_worker']['job_class'] = 'StuckImportJobsWorker'
Settings.cron_jobs['gitlab_usage_ping_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['gitlab_usage_ping_worker']['cron'] ||= Settings.__send__(:cron_random_weekly_time)
Settings.cron_jobs['gitlab_usage_ping_worker']['job_class'] = 'GitlabUsagePingWorker'
# Every day at 00:30
Settings.cron_jobs['schedule_update_user_activity_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['schedule_update_user_activity_worker']['cron'] ||= '30 0 * * *'
Settings.cron_jobs['schedule_update_user_activity_worker']['job_class'] = 'ScheduleUpdateUserActivityWorker'
Settings.cron_jobs['clear_shared_runners_minutes_worker'] ||= Settingslogic.new({}) Settings.cron_jobs['clear_shared_runners_minutes_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['clear_shared_runners_minutes_worker']['cron'] ||= '0 0 1 * *' Settings.cron_jobs['clear_shared_runners_minutes_worker']['cron'] ||= '0 0 1 * *'
...@@ -453,7 +461,7 @@ Settings.gitlab_shell['ssh_host'] ||= Settings.gitlab.ssh_host ...@@ -453,7 +461,7 @@ Settings.gitlab_shell['ssh_host'] ||= Settings.gitlab.ssh_host
Settings.gitlab_shell['ssh_port'] ||= 22 Settings.gitlab_shell['ssh_port'] ||= 22
Settings.gitlab_shell['ssh_user'] ||= Settings.gitlab.user Settings.gitlab_shell['ssh_user'] ||= Settings.gitlab.user
Settings.gitlab_shell['owner_group'] ||= Settings.gitlab.user Settings.gitlab_shell['owner_group'] ||= Settings.gitlab.user
Settings.gitlab_shell['ssh_path_prefix'] ||= Settings.send(:build_gitlab_shell_ssh_path_prefix) Settings.gitlab_shell['ssh_path_prefix'] ||= Settings.__send__(:build_gitlab_shell_ssh_path_prefix)
# #
# Repositories # Repositories
......
...@@ -100,11 +100,15 @@ namespace :admin do ...@@ -100,11 +100,15 @@ namespace :admin do
resource :application_settings, only: [:show, :update] do resource :application_settings, only: [:show, :update] do
resources :services, only: [:index, :edit, :update] resources :services, only: [:index, :edit, :update]
<<<<<<< HEAD
## EE-specific ## EE-specific
get :usage_data get :usage_data
## EE-specific ## EE-specific
=======
get :usage_data
>>>>>>> ce/master
put :reset_runners_token put :reset_runners_token
put :reset_health_check_token put :reset_health_check_token
put :clear_repository_check_states put :clear_repository_check_states
......
...@@ -54,6 +54,7 @@ ...@@ -54,6 +54,7 @@
- [pages, 1] - [pages, 1]
- [system_hook_push, 1] - [system_hook_push, 1]
- [update_user_activity, 1] - [update_user_activity, 1]
<<<<<<< HEAD
# EE specific queues # EE specific queues
- [geo, 1] - [geo, 1]
- [project_mirror, 1] - [project_mirror, 1]
...@@ -64,3 +65,5 @@ ...@@ -64,3 +65,5 @@
- [elastic_indexer, 1] - [elastic_indexer, 1]
- [elastic_commit_indexer, 1] - [elastic_commit_indexer, 1]
- [export_csv, 1] - [export_csv, 1]
=======
>>>>>>> ce/master
...@@ -21,7 +21,10 @@ var config = { ...@@ -21,7 +21,10 @@ var config = {
entry: { entry: {
blob: './blob_edit/blob_bundle.js', blob: './blob_edit/blob_bundle.js',
boards: './boards/boards_bundle.js', boards: './boards/boards_bundle.js',
<<<<<<< HEAD
burndown_chart: './burndown_chart/index.js', burndown_chart: './burndown_chart/index.js',
=======
>>>>>>> ce/master
common: './commons/index.js', common: './commons/index.js',
common_vue: ['vue', './vue_shared/common_vue.js'], common_vue: ['vue', './vue_shared/common_vue.js'],
common_d3: ['d3'], common_d3: ['d3'],
...@@ -129,8 +132,11 @@ var config = { ...@@ -129,8 +132,11 @@ var config = {
'notebook_viewer', 'notebook_viewer',
'pdf_viewer', 'pdf_viewer',
'pipelines', 'pipelines',
<<<<<<< HEAD
'mr_widget_ee', 'mr_widget_ee',
'issue_show' 'issue_show'
=======
>>>>>>> ce/master
], ],
minChunks: function(module, count) { minChunks: function(module, count) {
return module.resource && (/vue_shared/).test(module.resource); return module.resource && (/vue_shared/).test(module.resource);
......
class AddUsagePingToApplicationSettings < ActiveRecord::Migration class AddUsagePingToApplicationSettings < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers include Gitlab::Database::MigrationHelpers
<<<<<<< HEAD
=======
DOWNTIME = false
>>>>>>> ce/master
def change def change
add_column :application_settings, :usage_ping_enabled, :boolean, default: true, null: false add_column :application_settings, :usage_ping_enabled, :boolean, default: true, null: false
end end
......
class CreateUserActivities < ActiveRecord::Migration class CreateUserActivities < ActiveRecord::Migration
<<<<<<< HEAD
# Set this constant to true if this migration requires downtime. # Set this constant to true if this migration requires downtime.
DOWNTIME = true DOWNTIME = true
...@@ -23,5 +24,11 @@ class CreateUserActivities < ActiveRecord::Migration ...@@ -23,5 +24,11 @@ class CreateUserActivities < ActiveRecord::Migration
t.belongs_to :user, index: { unique: true }, foreign_key: { on_delete: :cascade } t.belongs_to :user, index: { unique: true }, foreign_key: { on_delete: :cascade }
t.datetime :last_activity_at, null: false t.datetime :last_activity_at, null: false
end end
=======
DOWNTIME = false
# This migration is a no-op. It just exists to match EE.
def change
>>>>>>> ce/master
end end
end end
class DeleteOrphanNotificationSettings < ActiveRecord::Migration
DOWNTIME = false
def up
execute("DELETE FROM notification_settings WHERE EXISTS (SELECT true FROM (#{orphan_notification_settings}) AS ns WHERE ns.id = notification_settings.id)")
end
def down
# This is a no-op method to make the migration reversible.
# If someone is trying to rollback for other reasons, we should not throw an Exception.
# raise ActiveRecord::IrreversibleMigration
end
def orphan_notification_settings
<<-SQL
SELECT notification_settings.id
FROM notification_settings
LEFT OUTER JOIN namespaces
ON namespaces.id = notification_settings.source_id
WHERE notification_settings.source_type = 'Namespace'
AND namespaces.id IS NULL
SQL
end
end
class AddIndexToSystemNoteMetadata < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
disable_ddl_transaction!
def up
# MySQL automatically creates an index on a foreign-key constraint; PostgreSQL does not
add_concurrent_index :system_note_metadata, :note_id, unique: true if Gitlab::Database.postgresql?
end
def down
remove_concurrent_index :system_note_metadata, :note_id, unique: true if Gitlab::Database.postgresql?
end
end
<<<<<<< HEAD
# See http://doc.gitlab.com/ce/development/migration_style_guide.html # See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab. # for more information on how to write migrations for GitLab.
=======
>>>>>>> ce/master
class DropUserActivitiesTable < ActiveRecord::Migration class DropUserActivitiesTable < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers include Gitlab::Database::MigrationHelpers
DOWNTIME = false DOWNTIME = false
<<<<<<< HEAD
# When using the methods "add_concurrent_index" or "add_column_with_default" # When using the methods "add_concurrent_index" or "add_column_with_default"
# you must disable the use of transactions as these methods can not run in an # you must disable the use of transactions as these methods can not run in an
# existing transaction. When using "add_concurrent_index" make sure that this # existing transaction. When using "add_concurrent_index" make sure that this
...@@ -30,5 +34,9 @@ class DropUserActivitiesTable < ActiveRecord::Migration ...@@ -30,5 +34,9 @@ class DropUserActivitiesTable < ActiveRecord::Migration
add_index "user_activities", ["user_id"], name: "index_user_activities_on_user_id", unique: true, using: :btree add_index "user_activities", ["user_id"], name: "index_user_activities_on_user_id", unique: true, using: :btree
end end
=======
# This migration is a no-op. It just exists to match EE.
def change
>>>>>>> ce/master
end end
end end
...@@ -11,7 +11,11 @@ ...@@ -11,7 +11,11 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
<<<<<<< HEAD
ActiveRecord::Schema.define(version: 20170419065104) do ActiveRecord::Schema.define(version: 20170419065104) do
=======
ActiveRecord::Schema.define(version: 20170419001229) do
>>>>>>> ce/master
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
...@@ -131,6 +135,7 @@ ActiveRecord::Schema.define(version: 20170419065104) do ...@@ -131,6 +135,7 @@ ActiveRecord::Schema.define(version: 20170419065104) do
t.integer "geo_status_timeout", default: 10 t.integer "geo_status_timeout", default: 10
t.string "uuid" t.string "uuid"
t.decimal "polling_interval_multiplier", default: 1.0, null: false t.decimal "polling_interval_multiplier", default: 1.0, null: false
<<<<<<< HEAD
t.boolean "elasticsearch_experimental_indexer" t.boolean "elasticsearch_experimental_indexer"
end end
...@@ -139,6 +144,10 @@ ActiveRecord::Schema.define(version: 20170419065104) do ...@@ -139,6 +144,10 @@ ActiveRecord::Schema.define(version: 20170419065104) do
t.integer "user_id", null: false t.integer "user_id", null: false
t.datetime "created_at" t.datetime "created_at"
t.datetime "updated_at" t.datetime "updated_at"
=======
t.boolean "usage_ping_enabled", default: true, null: false
t.string "uuid"
>>>>>>> ce/master
end end
create_table "approver_groups", force: :cascade do |t| create_table "approver_groups", force: :cascade do |t|
...@@ -1343,6 +1352,8 @@ ActiveRecord::Schema.define(version: 20170419065104) do ...@@ -1343,6 +1352,8 @@ ActiveRecord::Schema.define(version: 20170419065104) do
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
end end
add_index "system_note_metadata", ["note_id"], name: "index_system_note_metadata_on_note_id", unique: true, using: :btree
create_table "taggings", force: :cascade do |t| create_table "taggings", force: :cascade do |t|
t.integer "tag_id" t.integer "tag_id"
t.integer "taggable_id" t.integer "taggable_id"
......
...@@ -80,6 +80,7 @@ All technical content published by GitLab lives in the documentation, including: ...@@ -80,6 +80,7 @@ All technical content published by GitLab lives in the documentation, including:
- [Sidekiq Troubleshooting](administration/troubleshooting/sidekiq.md) Debug when Sidekiq appears hung and is not processing jobs. - [Sidekiq Troubleshooting](administration/troubleshooting/sidekiq.md) Debug when Sidekiq appears hung and is not processing jobs.
- [System hooks](system_hooks/system_hooks.md) Notifications when users, projects and keys are changed. - [System hooks](system_hooks/system_hooks.md) Notifications when users, projects and keys are changed.
- [Update](update/README.md) Update guides to upgrade your installation. - [Update](update/README.md) Update guides to upgrade your installation.
- [User cohorts](user/admin_area/user_cohorts.md) View user activity over time.
- [Web terminals](administration/integration/terminal.md) Provide terminal access to environments from within GitLab. - [Web terminals](administration/integration/terminal.md) Provide terminal access to environments from within GitLab.
- [Welcome message](customization/welcome_message.md) Add a custom welcome message to the sign-in page. - [Welcome message](customization/welcome_message.md) Add a custom welcome message to the sign-in page.
- [Downgrade back to CE](downgrade_ee_to_ce/README.md) Follow this guide if you need to downgrade from EE to CE. - [Downgrade back to CE](downgrade_ee_to_ce/README.md) Follow this guide if you need to downgrade from EE to CE.
......
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