summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorSimon Knox <psimyn@gmail.com>2018-01-16 14:48:49 +1100
committerSimon Knox <psimyn@gmail.com>2018-01-16 14:48:49 +1100
commit1644c1ac69248c59c982325f1d31b32a2b45e72e (patch)
tree67f776306c0ded6882c4293501fee31bd18a5f0b /app
parentc6884cfe66759f7ac2bb29efc2ed7e387910e6af (diff)
parent9e70ff345fa68d700b77b5939d34870ee61cb131 (diff)
downloadgitlab-ce-1644c1ac69248c59c982325f1d31b32a2b45e72e.tar.gz
Merge branch 'master' of gitlab.com:gitlab-org/gitlab-ce into dispatcher-projects-c
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/dispatcher.js118
-rw-r--r--app/assets/javascripts/pages/projects/branches/new/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/edit/index.js8
-rw-r--r--app/assets/javascripts/pages/projects/find_file/show/index.js12
-rw-r--r--app/assets/javascripts/pages/projects/forks/new/index.js5
-rw-r--r--app/assets/javascripts/pages/projects/imports/show/index.js5
-rw-r--r--app/assets/javascripts/pages/projects/issues/edit/index.js5
-rw-r--r--app/assets/javascripts/pages/projects/issues/form.js16
-rw-r--r--app/assets/javascripts/pages/projects/issues/index/index.js18
-rw-r--r--app/assets/javascripts/pages/projects/issues/new/index.js5
-rw-r--r--app/assets/javascripts/pages/projects/issues/show/index.js13
-rw-r--r--app/assets/javascripts/pages/projects/merge_requests/index/index.js16
-rw-r--r--app/assets/javascripts/pages/projects/tags/new/index.js9
-rw-r--r--app/assets/javascripts/pages/projects/tree/show/index.js15
-rw-r--r--app/assets/javascripts/pages/snippets/edit/index.js3
-rw-r--r--app/assets/javascripts/pages/snippets/form.js7
-rw-r--r--app/assets/javascripts/pages/snippets/new/index.js3
-rw-r--r--app/assets/javascripts/vue_shared/components/stacked_progress_bar.vue127
-rw-r--r--app/assets/stylesheets/framework.scss1
-rw-r--r--app/assets/stylesheets/framework/stacked-progress-bar.scss54
-rw-r--r--app/models/concerns/sha_attribute.rb1
-rw-r--r--app/models/repository.rb21
-rw-r--r--app/models/user.rb8
-rw-r--r--app/services/system_hooks_service.rb5
-rw-r--r--app/views/layouts/nav/sidebar/_group.html.haml12
-rw-r--r--app/views/projects/jobs/_empty_state.html.haml5
-rw-r--r--app/views/projects/jobs/show.html.haml7
-rw-r--r--app/workers/repository_fork_worker.rb5
28 files changed, 426 insertions, 81 deletions
diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js
index 892719c4e70..824f4184b43 100644
--- a/app/assets/javascripts/dispatcher.js
+++ b/app/assets/javascripts/dispatcher.js
@@ -1,42 +1,34 @@
/* eslint-disable func-names, space-before-function-paren, no-var, prefer-arrow-callback, wrap-iife, no-shadow, consistent-return, one-var, one-var-declaration-per-line, camelcase, default-case, no-new, quotes, no-duplicate-case, no-case-declarations, no-fallthrough, max-len */
import projectSelect from './project_select';
-import IssuableIndex from './issuable_index';
import Milestone from './milestone';
import IssuableForm from './issuable_form';
import LabelsSelect from './labels_select';
import MilestoneSelect from './milestone_select';
-import NewBranchForm from './new_branch_form';
import NotificationsForm from './notifications_form';
import notificationsDropdown from './notifications_dropdown';
import groupAvatar from './group_avatar';
import GroupLabelSubscription from './group_label_subscription';
import LineHighlighter from './line_highlighter';
-import NewCommitForm from './new_commit_form';
import Project from './project';
import projectAvatar from './project_avatar';
import MergeRequest from './merge_request';
import Compare from './compare';
import initCompareAutocomplete from './compare_autocomplete';
-import ProjectFindFile from './project_find_file';
import ProjectNew from './project_new';
-import projectImport from './project_import';
import Labels from './labels';
import LabelManager from './label_manager';
import Sidebar from './right_sidebar';
import IssuableTemplateSelectors from './templates/issuable_template_selectors';
import Flash from './flash';
-import Issue from './issue';
import BindInOut from './behaviors/bind_in_out';
import SecretValues from './behaviors/secret_values';
import Group from './group';
import ProjectsList from './projects_list';
-import setupProjectEdit from './project_edit';
import UserCallout from './user_callout';
import ShortcutsWiki from './shortcuts_wiki';
import BlobViewer from './blob/viewer/index';
import AutoWidthDropdownSelect from './issuable/auto_width_dropdown_select';
import UsersSelect from './users_select';
-import RefSelectDropdown from './ref_select_dropdown';
import GfmAutoComplete from './gfm_auto_complete';
import Star from './star';
import TreeView from './tree';
@@ -53,7 +45,6 @@ import GlFieldErrors from './gl_field_errors';
import GLForm from './gl_form';
import Shortcuts from './shortcuts';
import ShortcutsNavigation from './shortcuts_navigation';
-import ShortcutsFindFile from './shortcuts_find_file';
import ShortcutsIssuable from './shortcuts_issuable';
import U2FAuthenticate from './u2f/authenticate';
import Members from './members';
@@ -116,22 +107,22 @@ import Activities from './activities';
shortcut_handler = true;
break;
case 'projects:merge_requests:index':
+ import('./pages/projects/merge_requests/index')
+ .then(callDefault)
+ .catch(fail);
+ shortcut_handler = true;
+ break;
case 'projects:issues:index':
- if (filteredSearchEnabled) {
- const filteredSearchManager = new gl.FilteredSearchManager(page === 'projects:issues:index' ? 'issues' : 'merge_requests');
- filteredSearchManager.setup();
- }
- const pagePrefix = page === 'projects:merge_requests:index' ? 'merge_request_' : 'issue_';
- new IssuableIndex(pagePrefix);
-
- shortcut_handler = new ShortcutsNavigation();
- new UsersSelect();
+ import('./pages/projects/issues/index')
+ .then(callDefault)
+ .catch(fail);
+ shortcut_handler = true;
break;
case 'projects:issues:show':
- new Issue();
- shortcut_handler = new ShortcutsIssuable();
- new ZenMode();
- initIssuableSidebar();
+ import('./pages/projects/issues/show')
+ .then(callDefault)
+ .catch(fail);
+ shortcut_handler = true;
break;
case 'dashboard:milestones:index':
import('./pages/dashboard/milestones/index')
@@ -207,8 +198,14 @@ import Activities from './activities';
.catch(fail);
break;
case 'projects:branches:new':
+ import('./pages/projects/branches/new')
+ .then(callDefault)
+ .catch(fail);
+ break;
case 'projects:branches:create':
- new NewBranchForm($('.js-create-branch-form'), JSON.parse(document.getElementById('availableRefs').innerHTML));
+ import('./pages/projects/branches/new')
+ .then(callDefault)
+ .catch(fail);
break;
case 'projects:branches:index':
import('./pages/projects/branches/index')
@@ -216,13 +213,16 @@ import Activities from './activities';
.catch(fail);
break;
case 'projects:issues:new':
+ import('./pages/projects/issues/new')
+ .then(callDefault)
+ .catch(fail);
+ shortcut_handler = true;
+ break;
case 'projects:issues:edit':
- shortcut_handler = new ShortcutsNavigation();
- new GLForm($('.issue-form'), true);
- new IssuableForm($('.issue-form'));
- new LabelsSelect();
- new MilestoneSelect();
- new IssuableTemplateSelectors();
+ import('./pages/projects/issues/edit')
+ .then(callDefault)
+ .catch(fail);
+ shortcut_handler = true;
break;
case 'projects:merge_requests:creations:new':
const mrNewCompareNode = document.querySelector('.js-merge-request-new-compare');
@@ -250,9 +250,9 @@ import Activities from './activities';
new AutoWidthDropdownSelect($('.js-target-branch-select')).init();
break;
case 'projects:tags:new':
- new ZenMode();
- new GLForm($('.tag-form'), true);
- new RefSelectDropdown($('.js-branch-select'));
+ import('./pages/projects/tags/new')
+ .then(callDefault)
+ .catch(fail);
break;
case 'projects:snippets:show':
initNotes();
@@ -266,11 +266,24 @@ import Activities from './activities';
new ZenMode();
break;
case 'snippets:new':
+ import('./pages/snippets/new')
+ .then(callDefault)
+ .catch(fail);
+ break;
case 'snippets:edit':
+ import('./pages/snippets/edit')
+ .then(callDefault)
+ .catch(fail);
+ break;
case 'snippets:create':
+ import('./pages/snippets/new')
+ .then(callDefault)
+ .catch(fail);
+ break;
case 'snippets:update':
- new GLForm($('.snippet-form'), false);
- new ZenMode();
+ import('./pages/snippets/edit')
+ .then(callDefault)
+ .catch(fail);
break;
case 'projects:releases:edit':
new ZenMode();
@@ -334,12 +347,14 @@ import Activities from './activities';
});
break;
case 'projects:edit':
- setupProjectEdit();
- // Initialize expandable settings panels
- initSettingsPanels();
+ import('./pages/projects/edit')
+ .then(callDefault)
+ .catch(fail);
break;
case 'projects:imports:show':
- projectImport();
+ import('./pages/projects/imports/show')
+ .then(callDefault)
+ .catch(fail);
break;
case 'projects:pipelines:new':
case 'projects:pipelines:create':
@@ -399,22 +414,15 @@ import Activities from './activities';
groupAvatar();
break;
case 'projects:tree:show':
- shortcut_handler = new ShortcutsNavigation();
- new TreeView();
- new BlobViewer();
- new NewCommitForm($('.js-create-dir-form'));
- $('#tree-slider').waitForImages(function() {
- ajaxGet(document.querySelector('.js-tree-content').dataset.logsPath);
- });
+ import('./pages/projects/tree/show')
+ .then(callDefault)
+ .catch(fail);
+ shortcut_handler = true;
break;
case 'projects:find_file:show':
- const findElement = document.querySelector('.js-file-finder');
- const projectFindFile = new ProjectFindFile($(".file-finder-holder"), {
- url: findElement.dataset.fileFindUrl,
- treeUrl: findElement.dataset.findTreeUrl,
- blobUrlTemplate: findElement.dataset.blobUrlTemplate,
- });
- new ShortcutsFindFile(projectFindFile);
+ import('./pages/projects/find_file/show')
+ .then(callDefault)
+ .catch(fail);
shortcut_handler = true;
break;
case 'projects:blob:show':
@@ -468,7 +476,7 @@ import Activities from './activities';
shortcut_handler = true;
break;
case 'projects:forks:new':
- import(/* webpackChunkName: 'project_fork' */ './project_fork')
+ import('./pages/projects/forks/new')
.then(callDefault)
.catch(fail);
break;
@@ -525,7 +533,9 @@ import Activities from './activities';
import('./pages/admin/conversational_development_index/show').then(m => m.default()).catch(fail);
break;
case 'snippets:show':
- import('./pages/snippets/show').then(m => m.default()).catch(fail);
+ import('./pages/snippets/show')
+ .then(callDefault)
+ .catch(fail);
break;
case 'import:fogbugz:new_user_map':
import('./pages/import/fogbugz/new_user_map').then(m => m.default()).catch(fail);
diff --git a/app/assets/javascripts/pages/projects/branches/new/index.js b/app/assets/javascripts/pages/projects/branches/new/index.js
new file mode 100644
index 00000000000..ae5e033e97e
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/branches/new/index.js
@@ -0,0 +1,3 @@
+import NewBranchForm from '~/new_branch_form';
+
+export default () => new NewBranchForm($('.js-create-branch-form'), JSON.parse(document.getElementById('availableRefs').innerHTML));
diff --git a/app/assets/javascripts/pages/projects/edit/index.js b/app/assets/javascripts/pages/projects/edit/index.js
new file mode 100644
index 00000000000..7f662ef6b6a
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/edit/index.js
@@ -0,0 +1,8 @@
+import initSettingsPanels from '~/settings_panels';
+import setupProjectEdit from '~/project_edit';
+
+export default () => {
+ setupProjectEdit();
+ // Initialize expandable settings panels
+ initSettingsPanels();
+};
diff --git a/app/assets/javascripts/pages/projects/find_file/show/index.js b/app/assets/javascripts/pages/projects/find_file/show/index.js
new file mode 100644
index 00000000000..42bde0ff779
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/find_file/show/index.js
@@ -0,0 +1,12 @@
+import ProjectFindFile from '~/project_find_file';
+import ShortcutsFindFile from '~/shortcuts_find_file';
+
+export default () => {
+ const findElement = document.querySelector('.js-file-finder');
+ const projectFindFile = new ProjectFindFile($('.file-finder-holder'), {
+ url: findElement.dataset.fileFindUrl,
+ treeUrl: findElement.dataset.findTreeUrl,
+ blobUrlTemplate: findElement.dataset.blobUrlTemplate,
+ });
+ new ShortcutsFindFile(projectFindFile); // eslint-disable-line no-new
+};
diff --git a/app/assets/javascripts/pages/projects/forks/new/index.js b/app/assets/javascripts/pages/projects/forks/new/index.js
new file mode 100644
index 00000000000..7825eb01949
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/forks/new/index.js
@@ -0,0 +1,5 @@
+import ProjectFork from '~/project_fork';
+
+export default () => {
+ new ProjectFork(); // eslint-disable-line no-new
+};
diff --git a/app/assets/javascripts/pages/projects/imports/show/index.js b/app/assets/javascripts/pages/projects/imports/show/index.js
new file mode 100644
index 00000000000..378f7b3f38b
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/imports/show/index.js
@@ -0,0 +1,5 @@
+import ProjectImport from '~/project_import';
+
+export default () => {
+ new ProjectImport(); // eslint-disable-line no-new
+};
diff --git a/app/assets/javascripts/pages/projects/issues/edit/index.js b/app/assets/javascripts/pages/projects/issues/edit/index.js
new file mode 100644
index 00000000000..7f27f379d8c
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/issues/edit/index.js
@@ -0,0 +1,5 @@
+import initForm from '../form';
+
+export default () => {
+ initForm();
+};
diff --git a/app/assets/javascripts/pages/projects/issues/form.js b/app/assets/javascripts/pages/projects/issues/form.js
new file mode 100644
index 00000000000..5c7daf84738
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/issues/form.js
@@ -0,0 +1,16 @@
+/* eslint-disable no-new */
+import GLForm from '~/gl_form';
+import IssuableForm from '~/issuable_form';
+import LabelsSelect from '~/labels_select';
+import MilestoneSelect from '~/milestone_select';
+import ShortcutsNavigation from '~/shortcuts_navigation';
+import IssuableTemplateSelectors from '~/templates/issuable_template_selectors';
+
+export default () => {
+ new ShortcutsNavigation();
+ new GLForm($('.issue-form'), true);
+ new IssuableForm($('.issue-form'));
+ new LabelsSelect();
+ new MilestoneSelect();
+ new IssuableTemplateSelectors();
+};
diff --git a/app/assets/javascripts/pages/projects/issues/index/index.js b/app/assets/javascripts/pages/projects/issues/index/index.js
new file mode 100644
index 00000000000..fd395a45f00
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/issues/index/index.js
@@ -0,0 +1,18 @@
+
+/* eslint-disable no-new */
+
+import IssuableIndex from '~/issuable_index';
+import ShortcutsNavigation from '~/shortcuts_navigation';
+import UsersSelect from '~/users_select';
+
+export default () => {
+ const filteredSearchEnabled = gl.FilteredSearchManager && document.querySelector('.filtered-search');
+ if (filteredSearchEnabled) {
+ const filteredSearchManager = new gl.FilteredSearchManager('issues');
+ filteredSearchManager.setup();
+ }
+ new IssuableIndex('issue_');
+
+ new ShortcutsNavigation();
+ new UsersSelect();
+};
diff --git a/app/assets/javascripts/pages/projects/issues/new/index.js b/app/assets/javascripts/pages/projects/issues/new/index.js
new file mode 100644
index 00000000000..7f27f379d8c
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/issues/new/index.js
@@ -0,0 +1,5 @@
+import initForm from '../form';
+
+export default () => {
+ initForm();
+};
diff --git a/app/assets/javascripts/pages/projects/issues/show/index.js b/app/assets/javascripts/pages/projects/issues/show/index.js
new file mode 100644
index 00000000000..48ed8fb2243
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/issues/show/index.js
@@ -0,0 +1,13 @@
+
+/* eslint-disable no-new */
+import initIssuableSidebar from '~/init_issuable_sidebar';
+import Issue from '~/issue';
+import ShortcutsIssuable from '~/shortcuts_issuable';
+import ZenMode from '~/zen_mode';
+
+export default () => {
+ new Issue();
+ new ShortcutsIssuable();
+ new ZenMode();
+ initIssuableSidebar();
+};
diff --git a/app/assets/javascripts/pages/projects/merge_requests/index/index.js b/app/assets/javascripts/pages/projects/merge_requests/index/index.js
new file mode 100644
index 00000000000..a52bea03aa2
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/merge_requests/index/index.js
@@ -0,0 +1,16 @@
+import IssuableIndex from '~/issuable_index';
+import ShortcutsNavigation from '~/shortcuts_navigation';
+import UsersSelect from '~/users_select';
+
+export default () => {
+ const filteredSearchEnabled = gl.FilteredSearchManager && document.querySelector('.filtered-search');
+
+ if (filteredSearchEnabled) {
+ const filteredSearchManager = new gl.FilteredSearchManager('merge_requests');
+ filteredSearchManager.setup();
+ }
+
+ new IssuableIndex('merge_request_'); // eslint-disable-line no-new
+ new ShortcutsNavigation(); // eslint-disable-line no-new
+ new UsersSelect(); // eslint-disable-line no-new
+};
diff --git a/app/assets/javascripts/pages/projects/tags/new/index.js b/app/assets/javascripts/pages/projects/tags/new/index.js
new file mode 100644
index 00000000000..dacc2875c8c
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/tags/new/index.js
@@ -0,0 +1,9 @@
+import RefSelectDropdown from '../../../../ref_select_dropdown';
+import ZenMode from '../../../../zen_mode';
+import GLForm from '../../../../gl_form';
+
+export default () => {
+ new ZenMode(); // eslint-disable-line no-new
+ new GLForm($('.tag-form'), true); // eslint-disable-line no-new
+ new RefSelectDropdown($('.js-branch-select')); // eslint-disable-line no-new
+};
diff --git a/app/assets/javascripts/pages/projects/tree/show/index.js b/app/assets/javascripts/pages/projects/tree/show/index.js
new file mode 100644
index 00000000000..28a0160f47d
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/tree/show/index.js
@@ -0,0 +1,15 @@
+import TreeView from '../../../../tree';
+import ShortcutsNavigation from '../../../../shortcuts_navigation';
+import BlobViewer from '../../../../blob/viewer';
+import NewCommitForm from '../../../../new_commit_form';
+import { ajaxGet } from '../../../../lib/utils/common_utils';
+
+export default () => {
+ new ShortcutsNavigation(); // eslint-disable-line no-new
+ new TreeView(); // eslint-disable-line no-new
+ new BlobViewer(); // eslint-disable-line no-new
+ new NewCommitForm($('.js-create-dir-form')); // eslint-disable-line no-new
+ $('#tree-slider').waitForImages(() =>
+ ajaxGet(document.querySelector('.js-tree-content').dataset.logsPath));
+};
+
diff --git a/app/assets/javascripts/pages/snippets/edit/index.js b/app/assets/javascripts/pages/snippets/edit/index.js
new file mode 100644
index 00000000000..9c664b5f1ff
--- /dev/null
+++ b/app/assets/javascripts/pages/snippets/edit/index.js
@@ -0,0 +1,3 @@
+import form from '../form';
+
+export default form;
diff --git a/app/assets/javascripts/pages/snippets/form.js b/app/assets/javascripts/pages/snippets/form.js
new file mode 100644
index 00000000000..f996d3cd74e
--- /dev/null
+++ b/app/assets/javascripts/pages/snippets/form.js
@@ -0,0 +1,7 @@
+import GLForm from '~/gl_form';
+import ZenMode from '~/zen_mode';
+
+export default () => {
+ new GLForm($('.snippet-form'), false); // eslint-disable-line no-new
+ new ZenMode(); // eslint-disable-line no-new
+};
diff --git a/app/assets/javascripts/pages/snippets/new/index.js b/app/assets/javascripts/pages/snippets/new/index.js
new file mode 100644
index 00000000000..9c664b5f1ff
--- /dev/null
+++ b/app/assets/javascripts/pages/snippets/new/index.js
@@ -0,0 +1,3 @@
+import form from '../form';
+
+export default form;
diff --git a/app/assets/javascripts/vue_shared/components/stacked_progress_bar.vue b/app/assets/javascripts/vue_shared/components/stacked_progress_bar.vue
new file mode 100644
index 00000000000..86f06c8d266
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/stacked_progress_bar.vue
@@ -0,0 +1,127 @@
+<script>
+import tooltip from '~/vue_shared/directives/tooltip';
+
+export default {
+ directives: {
+ tooltip,
+ },
+ props: {
+ cssClass: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ successLabel: {
+ type: String,
+ required: true,
+ },
+ failureLabel: {
+ type: String,
+ required: true,
+ },
+ neutralLabel: {
+ type: String,
+ required: true,
+ },
+ successCount: {
+ type: Number,
+ required: true,
+ },
+ failureCount: {
+ type: Number,
+ required: true,
+ },
+ totalCount: {
+ type: Number,
+ required: true,
+ },
+ },
+ computed: {
+ neutralCount() {
+ return this.totalCount - this.successCount - this.failureCount;
+ },
+ successPercent() {
+ return this.getPercent(this.successCount);
+ },
+ successBarStyle() {
+ return this.barStyle(this.successPercent);
+ },
+ successTooltip() {
+ return this.getTooltip(this.successLabel, this.successCount);
+ },
+ failurePercent() {
+ return this.getPercent(this.failureCount);
+ },
+ failureBarStyle() {
+ return this.barStyle(this.failurePercent);
+ },
+ failureTooltip() {
+ return this.getTooltip(this.failureLabel, this.failureCount);
+ },
+ neutralPercent() {
+ return this.getPercent(this.neutralCount);
+ },
+ neutralBarStyle() {
+ return this.barStyle(this.neutralPercent);
+ },
+ neutralTooltip() {
+ return this.getTooltip(this.neutralLabel, this.neutralCount);
+ },
+ },
+ methods: {
+ getPercent(count) {
+ return Math.ceil((count / this.totalCount) * 100);
+ },
+ barStyle(percent) {
+ return `width: ${percent}%;`;
+ },
+ getTooltip(label, count) {
+ return `${label}: ${count}`;
+ },
+ },
+};
+</script>
+
+<template>
+ <div
+ class="stacked-progress-bar"
+ :class="cssClass"
+ >
+ <span
+ v-if="!totalCount"
+ class="status-unavailable"
+ >
+ {{ __("Not available") }}
+ </span>
+ <span
+ v-tooltip
+ v-if="successPercent"
+ class="status-green"
+ data-placement="bottom"
+ :title="successTooltip"
+ :style="successBarStyle"
+ >
+ {{ successPercent }}%
+ </span>
+ <span
+ v-tooltip
+ v-if="neutralPercent"
+ class="status-neutral"
+ data-placement="bottom"
+ :title="neutralTooltip"
+ :style="neutralBarStyle"
+ >
+ {{ neutralPercent }}%
+ </span>
+ <span
+ v-tooltip
+ v-if="failurePercent"
+ class="status-red"
+ data-placement="bottom"
+ :title="failureTooltip"
+ :style="failureBarStyle"
+ >
+ {{ failurePercent }}%
+ </span>
+ </div>
+</template>
diff --git a/app/assets/stylesheets/framework.scss b/app/assets/stylesheets/framework.scss
index 43b16d3cf7d..cff47ea76ec 100644
--- a/app/assets/stylesheets/framework.scss
+++ b/app/assets/stylesheets/framework.scss
@@ -59,3 +59,4 @@
@import "framework/snippets";
@import "framework/memory_graph";
@import "framework/responsive_tables";
+@import "framework/stacked-progress-bar";
diff --git a/app/assets/stylesheets/framework/stacked-progress-bar.scss b/app/assets/stylesheets/framework/stacked-progress-bar.scss
new file mode 100644
index 00000000000..4869cda73e5
--- /dev/null
+++ b/app/assets/stylesheets/framework/stacked-progress-bar.scss
@@ -0,0 +1,54 @@
+.stacked-progress-bar {
+ display: flex;
+ height: 16px;
+ border-radius: 10px;
+ overflow: hidden;
+ background-color: $theme-gray-100;
+
+ .status-unavailable,
+ .status-green,
+ .status-neutral,
+ .status-red, {
+ height: 100%;
+ min-width: 25px;
+ padding: 0 5px;
+ font-size: $tooltip-font-size;
+ font-weight: normal;
+ color: $white-light;
+ line-height: 16px;
+
+ &:hover {
+ cursor: pointer;
+ }
+ }
+
+ .status-unavailable {
+ padding: 0 10px;
+ color: $theme-gray-700;
+ }
+
+ .status-green {
+ background-color: $green-500;
+
+ &:hover {
+ background-color: $green-600;
+ }
+ }
+
+ .status-neutral {
+ background-color: $theme-gray-200;
+ color: $gl-gray-dark;
+
+ &:hover {
+ background-color: $theme-gray-300;
+ }
+ }
+
+ .status-red {
+ background-color: $red-500;
+
+ &:hover {
+ background-color: $red-600;
+ }
+ }
+}
diff --git a/app/models/concerns/sha_attribute.rb b/app/models/concerns/sha_attribute.rb
index 67ecf470f7e..703a72c355c 100644
--- a/app/models/concerns/sha_attribute.rb
+++ b/app/models/concerns/sha_attribute.rb
@@ -3,6 +3,7 @@ module ShaAttribute
module ClassMethods
def sha_attribute(name)
+ return if ENV['STATIC_VERIFICATION']
return unless table_exists?
column = columns.find { |c| c.name == name.to_s }
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 8e9f33c174c..2ffd9558ebc 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -831,13 +831,12 @@ class Repository
end
def can_be_merged?(source_sha, target_branch)
- our_commit = rugged.branches[target_branch].target
- their_commit = rugged.lookup(source_sha)
-
- if our_commit && their_commit
- !rugged.merge_commits(our_commit, their_commit).conflicts?
- else
- false
+ raw_repository.gitaly_migrate(:can_be_merged) do |is_enabled|
+ if is_enabled
+ gitaly_can_be_merged?(source_sha, find_branch(target_branch).target)
+ else
+ rugged_can_be_merged?(source_sha, target_branch)
+ end
end
end
@@ -1132,6 +1131,14 @@ class Repository
Gitlab::Git::Repository.new(project.repository_storage, disk_path + '.git', Gitlab::GlRepository.gl_repository(project, is_wiki))
end
+ def gitaly_can_be_merged?(their_commit, our_commit)
+ !raw_repository.gitaly_conflicts_client(our_commit, their_commit).conflicts?
+ end
+
+ def rugged_can_be_merged?(their_commit, our_commit)
+ !rugged.merge_commits(our_commit, their_commit).conflicts?
+ end
+
def find_commits_by_message_by_shelling_out(query, ref, path, limit, offset)
ref ||= root_ref
diff --git a/app/models/user.rb b/app/models/user.rb
index 4484ee9ff4c..09aa5a7b318 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -53,7 +53,10 @@ class User < ActiveRecord::Base
serialize :otp_backup_codes, JSON # rubocop:disable Cop/ActiveRecordSerialize
devise :lockable, :recoverable, :rememberable, :trackable,
- :validatable, :omniauthable, :confirmable, :registerable
+ :validatable, :omniauthable, :confirmable, :registerable
+
+ BLOCKED_MESSAGE = "Your account has been blocked. Please contact your GitLab " \
+ "administrator if you think this is an error.".freeze
# Override Devise::Models::Trackable#update_tracked_fields!
# to limit database writes to at most once every hour
@@ -217,8 +220,7 @@ class User < ActiveRecord::Base
end
def inactive_message
- "Your account has been blocked. Please contact your GitLab " \
- "administrator if you think this is an error."
+ BLOCKED_MESSAGE
end
end
end
diff --git a/app/services/system_hooks_service.rb b/app/services/system_hooks_service.rb
index 690918b4a00..af6d77ef5e8 100644
--- a/app/services/system_hooks_service.rb
+++ b/app/services/system_hooks_service.rb
@@ -41,8 +41,11 @@ class SystemHooksService
when User
data.merge!(user_data(model))
- if event == :rename
+ case event
+ when :rename
data[:old_username] = model.username_was
+ when :failed_login
+ data[:state] = model.state
end
when ProjectMember
data.merge!(project_member_data(model))
diff --git a/app/views/layouts/nav/sidebar/_group.html.haml b/app/views/layouts/nav/sidebar/_group.html.haml
index 0c27b09f7b1..96aae06a9df 100644
--- a/app/views/layouts/nav/sidebar/_group.html.haml
+++ b/app/views/layouts/nav/sidebar/_group.html.haml
@@ -1,5 +1,5 @@
-- issues = IssuesFinder.new(current_user, group_id: @group.id, state: 'opened').execute
-- merge_requests = MergeRequestsFinder.new(current_user, group_id: @group.id, state: 'opened', non_archived: true).execute
+- issues_count = IssuesFinder.new(current_user, group_id: @group.id, state: 'opened').execute.count
+- merge_requests_count = MergeRequestsFinder.new(current_user, group_id: @group.id, state: 'opened', non_archived: true).execute.count
.nav-sidebar{ class: ("sidebar-collapsed-desktop" if collapsed_sidebar?) }
.nav-sidebar-inner-scroll
@@ -39,14 +39,14 @@
= sprite_icon('issues')
%span.nav-item-name
Issues
- %span.badge.count= number_with_delimiter(issues.count)
+ %span.badge.count= number_with_delimiter(issues_count)
%ul.sidebar-sub-level-items
= nav_link(path: ['groups#issues', 'labels#index', 'milestones#index'], html_options: { class: "fly-out-top-item" } ) do
= link_to issues_group_path(@group) do
%strong.fly-out-top-item-name
#{ _('Issues') }
- %span.badge.count.issue_counter.fly-out-badge= number_with_delimiter(issues.count)
+ %span.badge.count.issue_counter.fly-out-badge= number_with_delimiter(issues_count)
%li.divider.fly-out-top-item
= nav_link(path: 'groups#issues', html_options: { class: 'home' }) do
= link_to issues_group_path(@group), title: 'List' do
@@ -69,13 +69,13 @@
= sprite_icon('git-merge')
%span.nav-item-name
Merge Requests
- %span.badge.count= number_with_delimiter(merge_requests.count)
+ %span.badge.count= number_with_delimiter(merge_requests_count)
%ul.sidebar-sub-level-items.is-fly-out-only
= nav_link(path: 'groups#merge_requests', html_options: { class: "fly-out-top-item" } ) do
= link_to merge_requests_group_path(@group) do
%strong.fly-out-top-item-name
#{ _('Merge Requests') }
- %span.badge.count.merge_counter.js-merge-counter.fly-out-badge= number_with_delimiter(merge_requests.count)
+ %span.badge.count.merge_counter.js-merge-counter.fly-out-badge= number_with_delimiter(merge_requests_count)
= nav_link(path: 'group_members#index') do
= link_to group_group_members_path(@group) do
.nav-icon-container
diff --git a/app/views/projects/jobs/_empty_state.html.haml b/app/views/projects/jobs/_empty_state.html.haml
index c66313bdbf3..311934d9c33 100644
--- a/app/views/projects/jobs/_empty_state.html.haml
+++ b/app/views/projects/jobs/_empty_state.html.haml
@@ -1,7 +1,7 @@
- illustration = local_assigns.fetch(:illustration)
- illustration_size = local_assigns.fetch(:illustration_size)
- title = local_assigns.fetch(:title)
-- content = local_assigns.fetch(:content)
+- content = local_assigns.fetch(:content, nil)
- action = local_assigns.fetch(:action, nil)
.row.empty-state
@@ -11,7 +11,8 @@
.col-xs-12
.text-content
%h4.text-center= title
- %p= content
+ - if content
+ %p= content
- if action
.text-center
= action
diff --git a/app/views/projects/jobs/show.html.haml b/app/views/projects/jobs/show.html.haml
index 8b05440fc78..1e6d6f67e66 100644
--- a/app/views/projects/jobs/show.html.haml
+++ b/app/views/projects/jobs/show.html.haml
@@ -93,14 +93,13 @@
illustration: 'illustrations/manual_action.svg',
illustration_size: 'svg-394',
title: _('This job requires a manual action'),
- content: _('This job depends on a user to trigger its process. Often they are used to deploy code to production environments.'),
- action: ( link_to _('Trigger this manual action'), play_project_job_path(@project, @build), class: 'btn btn-primary', title: _('Trigger this manual action') )
+ content: _('This job depends on a user to trigger its process. Often they are used to deploy code to production environments'),
+ action: ( link_to _('Trigger this manual action'), play_project_job_path(@project, @build), method: :post, class: 'btn btn-primary', title: _('Trigger this manual action') )
- else
= render 'empty_state',
illustration: 'illustrations/job_not_triggered.svg',
illustration_size: 'svg-306',
- title: _('This job has not been triggered yet'),
- content: _('This job depends on upstream jobs that need to succeed in order for this job to be triggered.')
+ title: _('This job has not been triggered yet')
= render "sidebar"
diff --git a/app/workers/repository_fork_worker.rb b/app/workers/repository_fork_worker.rb
index d1c57b82681..07584fab7c8 100644
--- a/app/workers/repository_fork_worker.rb
+++ b/app/workers/repository_fork_worker.rb
@@ -17,10 +17,7 @@ class RepositoryForkWorker
project.repository_storage_path, project.disk_path)
raise "Unable to fork project #{project_id} for repository #{source_disk_path} -> #{project.disk_path}" unless result
- project.repository.after_import
- raise "Project #{project_id} had an invalid repository after fork" unless project.valid_repo?
-
- project.import_finish
+ project.after_import
end
private