Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-02-24 15:09:00 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-02-24 15:09:00 +0300
commitae78b85a25cb0c19c3d6a2e4e6c7ca91ed50787d (patch)
treec53ad0fcdab26725814f1dc5267f6a04ebe4cf73 /app
parent38149afcf95e7669a7a99828c579d185b70c04dc (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/diff_notes/components/resolve_discussion_btn.js70
-rw-r--r--app/assets/javascripts/diff_notes/diff_notes_bundle.js3
-rw-r--r--app/assets/javascripts/filtered_search/available_dropdown_mappings.js4
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js14
-rw-r--r--app/assets/javascripts/filtered_search/filtered_search_manager.js23
-rw-r--r--app/assets/javascripts/filtered_search/visual_token_value.js35
-rw-r--r--app/assets/javascripts/self_monitor/components/self_monitor_form.vue2
-rw-r--r--app/assets/javascripts/self_monitor/store/state.js2
-rw-r--r--app/assets/stylesheets/framework/dropdowns.scss9
-rw-r--r--app/finders/serverless_domain_finder.rb2
-rw-r--r--app/models/serverless/lookup_path.rb30
-rw-r--r--app/models/serverless/virtual_domain.rb22
-rw-r--r--app/services/ci/register_job_service.rb10
-rw-r--r--app/views/discussions/_resolve_all.html.haml8
-rw-r--r--app/views/shared/issuable/_search_bar.html.haml2
15 files changed, 135 insertions, 101 deletions
diff --git a/app/assets/javascripts/diff_notes/components/resolve_discussion_btn.js b/app/assets/javascripts/diff_notes/components/resolve_discussion_btn.js
deleted file mode 100644
index 5f2a17da630..00000000000
--- a/app/assets/javascripts/diff_notes/components/resolve_discussion_btn.js
+++ /dev/null
@@ -1,70 +0,0 @@
-/* eslint-disable no-else-return */
-/* global CommentsStore */
-/* global ResolveService */
-
-import Vue from 'vue';
-import { __ } from '~/locale';
-
-const ResolveDiscussionBtn = Vue.extend({
- props: {
- discussionId: {
- type: String,
- required: true,
- },
- mergeRequestId: {
- type: Number,
- required: true,
- },
- canResolve: {
- type: Boolean,
- required: true,
- },
- },
- data() {
- return {
- discussion: {},
- };
- },
- computed: {
- showButton() {
- if (this.discussion) {
- return this.discussion.isResolvable();
- } else {
- return false;
- }
- },
- isDiscussionResolved() {
- if (this.discussion) {
- return this.discussion.isResolved();
- } else {
- return false;
- }
- },
- buttonText() {
- if (this.isDiscussionResolved) {
- return __('Unresolve discussion');
- } else {
- return __('Resolve discussion');
- }
- },
- loading() {
- if (this.discussion) {
- return this.discussion.loading;
- } else {
- return false;
- }
- },
- },
- created() {
- CommentsStore.createDiscussion(this.discussionId, this.canResolve);
-
- this.discussion = CommentsStore.state[this.discussionId];
- },
- methods: {
- resolve() {
- ResolveService.toggleResolveForDiscussion(this.mergeRequestId, this.discussionId);
- },
- },
-});
-
-Vue.component('resolve-discussion-btn', ResolveDiscussionBtn);
diff --git a/app/assets/javascripts/diff_notes/diff_notes_bundle.js b/app/assets/javascripts/diff_notes/diff_notes_bundle.js
index 7dcf3594471..92862d4c933 100644
--- a/app/assets/javascripts/diff_notes/diff_notes_bundle.js
+++ b/app/assets/javascripts/diff_notes/diff_notes_bundle.js
@@ -11,7 +11,6 @@ import './components/comment_resolve_btn';
import './components/jump_to_discussion';
import './components/resolve_btn';
import './components/resolve_count';
-import './components/resolve_discussion_btn';
import './components/diff_note_avatars';
import './components/new_issue_for_discussion';
@@ -20,7 +19,7 @@ export default () => {
document.querySelector('.merge-request') || document.querySelector('.commit-box');
const { projectPath } = projectPathHolder.dataset;
const COMPONENT_SELECTOR =
- 'resolve-btn, resolve-discussion-btn, jump-to-discussion, comment-and-resolve-btn, new-issue-for-discussion-btn';
+ 'resolve-btn, jump-to-discussion, comment-and-resolve-btn, new-issue-for-discussion-btn';
window.gl = window.gl || {};
window.gl.diffNoteApps = {};
diff --git a/app/assets/javascripts/filtered_search/available_dropdown_mappings.js b/app/assets/javascripts/filtered_search/available_dropdown_mappings.js
index 5450abf4cbd..692b41da965 100644
--- a/app/assets/javascripts/filtered_search/available_dropdown_mappings.js
+++ b/app/assets/javascripts/filtered_search/available_dropdown_mappings.js
@@ -9,7 +9,7 @@ import DropdownUtils from './dropdown_utils';
import { mergeUrlParams } from '../lib/utils/url_utility';
export default class AvailableDropdownMappings {
- constructor(
+ constructor({
container,
runnerTagsEndpoint,
labelsEndpoint,
@@ -18,7 +18,7 @@ export default class AvailableDropdownMappings {
groupsOnly,
includeAncestorGroups,
includeDescendantGroups,
- ) {
+ }) {
this.container = container;
this.runnerTagsEndpoint = runnerTagsEndpoint;
this.labelsEndpoint = labelsEndpoint;
diff --git a/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js b/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js
index 566fb295588..03f65612b60 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js
@@ -13,6 +13,7 @@ export default class FilteredSearchDropdownManager {
labelsEndpoint = '',
milestonesEndpoint = '',
releasesEndpoint = '',
+ epicsEndpoint = '',
tokenizer,
page,
isGroup,
@@ -27,6 +28,7 @@ export default class FilteredSearchDropdownManager {
this.labelsEndpoint = removeTrailingSlash(labelsEndpoint);
this.milestonesEndpoint = removeTrailingSlash(milestonesEndpoint);
this.releasesEndpoint = removeTrailingSlash(releasesEndpoint);
+ this.epicsEndpoint = removeTrailingSlash(epicsEndpoint);
this.tokenizer = tokenizer;
this.filteredSearchTokenKeys = filteredSearchTokenKeys || FilteredSearchTokenKeys;
this.filteredSearchInput = this.container.querySelector('.filtered-search');
@@ -54,16 +56,8 @@ export default class FilteredSearchDropdownManager {
setupMapping() {
const supportedTokens = this.filteredSearchTokenKeys.getKeys();
- const availableMappings = new AvailableDropdownMappings(
- this.container,
- this.runnerTagsEndpoint,
- this.labelsEndpoint,
- this.milestonesEndpoint,
- this.releasesEndpoint,
- this.groupsOnly,
- this.includeAncestorGroups,
- this.includeDescendantGroups,
- );
+
+ const availableMappings = new AvailableDropdownMappings({ ...this });
this.mapping = availableMappings.getAllowedMappings(supportedTokens);
}
diff --git a/app/assets/javascripts/filtered_search/filtered_search_manager.js b/app/assets/javascripts/filtered_search/filtered_search_manager.js
index 0b4f9457c54..e9a714605c7 100644
--- a/app/assets/javascripts/filtered_search/filtered_search_manager.js
+++ b/app/assets/javascripts/filtered_search/filtered_search_manager.js
@@ -45,6 +45,11 @@ export default class FilteredSearchManager {
this.filteredSearchTokenKeys.enableMultipleAssignees();
}
+ const { epicsEndpoint } = this.filteredSearchInput.dataset;
+ if (!epicsEndpoint && this.filteredSearchTokenKeys.removeEpicToken) {
+ this.filteredSearchTokenKeys.removeEpicToken();
+ }
+
this.recentSearchesStore = new RecentSearchesStore({
isLocalStorageAvailable: RecentSearchesService.isAvailable(),
allowedKeys: this.filteredSearchTokenKeys.getKeys(),
@@ -88,12 +93,20 @@ export default class FilteredSearchManager {
if (this.filteredSearchInput) {
this.tokenizer = FilteredSearchTokenizer;
+ const {
+ runnerTagsEndpoint = '',
+ labelsEndpoint = '',
+ milestonesEndpoint = '',
+ releasesEndpoint = '',
+ epicsEndpoint = '',
+ } = this.filteredSearchInput.dataset;
+
this.dropdownManager = new FilteredSearchDropdownManager({
- runnerTagsEndpoint:
- this.filteredSearchInput.getAttribute('data-runner-tags-endpoint') || '',
- labelsEndpoint: this.filteredSearchInput.getAttribute('data-labels-endpoint') || '',
- milestonesEndpoint: this.filteredSearchInput.getAttribute('data-milestones-endpoint') || '',
- releasesEndpoint: this.filteredSearchInput.getAttribute('data-releases-endpoint') || '',
+ runnerTagsEndpoint,
+ labelsEndpoint,
+ milestonesEndpoint,
+ releasesEndpoint,
+ epicsEndpoint,
tokenizer: this.tokenizer,
page: this.page,
isGroup: this.isGroup,
diff --git a/app/assets/javascripts/filtered_search/visual_token_value.js b/app/assets/javascripts/filtered_search/visual_token_value.js
index 9f3cf881af4..b7ac655b619 100644
--- a/app/assets/javascripts/filtered_search/visual_token_value.js
+++ b/app/assets/javascripts/filtered_search/visual_token_value.js
@@ -28,6 +28,8 @@ export default class VisualTokenValue {
this.updateUserTokenAppearance(tokenValueContainer, tokenValueElement);
} else if (tokenType === 'my-reaction') {
this.updateEmojiTokenAppearance(tokenValueContainer, tokenValueElement);
+ } else if (tokenType === 'epic') {
+ this.updateEpicLabel(tokenValueContainer, tokenValueElement);
}
}
@@ -83,6 +85,39 @@ export default class VisualTokenValue {
.catch(() => new Flash(__('An error occurred while fetching label colors.')));
}
+ updateEpicLabel(tokenValueContainer) {
+ const tokenValue = this.tokenValue.replace(/^&/, '');
+ const filteredSearchInput = FilteredSearchContainer.container.querySelector('.filtered-search');
+ const { epicsEndpoint } = filteredSearchInput.dataset;
+ const epicsEndpointWithParams = FilteredSearchVisualTokens.getEndpointWithQueryParams(
+ `${epicsEndpoint}.json`,
+ filteredSearchInput.dataset.endpointQueryParams,
+ );
+
+ return AjaxCache.retrieve(epicsEndpointWithParams)
+ .then(epics => {
+ const matchingEpic = (epics || []).find(epic => epic.id === Number(tokenValue));
+
+ if (!matchingEpic) {
+ return;
+ }
+
+ VisualTokenValue.replaceEpicTitle(tokenValueContainer, matchingEpic.title, matchingEpic.id);
+ })
+ .catch(() => new Flash(__('An error occurred while adding formatted title for epic')));
+ }
+
+ static replaceEpicTitle(tokenValueContainer, epicTitle, epicId) {
+ const tokenContainer = tokenValueContainer;
+
+ const valueContainer = tokenContainer.querySelector('.value');
+
+ if (valueContainer) {
+ tokenContainer.dataset.originalValue = valueContainer.innerText;
+ valueContainer.innerText = `"${epicTitle}"::&${epicId}`;
+ }
+ }
+
static setTokenStyle(tokenValueContainer, backgroundColor, textColor) {
const token = tokenValueContainer;
diff --git a/app/assets/javascripts/self_monitor/components/self_monitor_form.vue b/app/assets/javascripts/self_monitor/components/self_monitor_form.vue
index 6b19a72317c..1e203d332db 100644
--- a/app/assets/javascripts/self_monitor/components/self_monitor_form.vue
+++ b/app/assets/javascripts/self_monitor/components/self_monitor_form.vue
@@ -129,7 +129,7 @@ export default {
</div>
<div class="settings-content">
<form name="self-monitoring-form">
- <p v-html="selfMonitoringFormText"></p>
+ <p ref="selfMonitoringFormText" v-html="selfMonitoringFormText"></p>
<gl-form-group :label="$options.formLabels.createProject" label-for="self-monitor-toggle">
<gl-toggle
v-model="selfMonitorEnabled"
diff --git a/app/assets/javascripts/self_monitor/store/state.js b/app/assets/javascripts/self_monitor/store/state.js
index a0ce88ff58c..582ce5576f1 100644
--- a/app/assets/javascripts/self_monitor/store/state.js
+++ b/app/assets/javascripts/self_monitor/store/state.js
@@ -9,7 +9,7 @@ export default (initialState = {}) => ({
deleteProjectStatusEndpoint: initialState.statusDeleteSelfMonitoringProjectPath || '',
selfMonitorProjectPath: initialState.selfMonitoringProjectFullPath || '',
showAlert: false,
- projectPath: '',
+ projectPath: initialState.selfMonitoringProjectFullPath || '',
loading: false,
alertContent: {},
});
diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss
index 005e5efbdaf..53a642d68ce 100644
--- a/app/assets/stylesheets/framework/dropdowns.scss
+++ b/app/assets/stylesheets/framework/dropdowns.scss
@@ -410,6 +410,15 @@
}
}
+ > button.dropdown-epic-button {
+ flex-direction: column;
+
+ .reference {
+ color: $gl-gray-400;
+ margin-top: $gl-padding-4;
+ }
+ }
+
&.droplab-item-selected i {
visibility: visible;
}
diff --git a/app/finders/serverless_domain_finder.rb b/app/finders/serverless_domain_finder.rb
index 3a8a55022bb..661cd0ca363 100644
--- a/app/finders/serverless_domain_finder.rb
+++ b/app/finders/serverless_domain_finder.rb
@@ -11,7 +11,7 @@ class ServerlessDomainFinder
return unless serverless?
@serverless_domain_cluster = ::Serverless::DomainCluster.for_uuid(serverless_domain_cluster_uuid)
- return unless serverless_domain_cluster
+ return unless serverless_domain_cluster&.knative&.external_ip
@environment = ::Environment.for_id_and_slug(match[:environment_id].to_i(16), match[:environment_slug])
return unless environment
diff --git a/app/models/serverless/lookup_path.rb b/app/models/serverless/lookup_path.rb
new file mode 100644
index 00000000000..c09b3718651
--- /dev/null
+++ b/app/models/serverless/lookup_path.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+module Serverless
+ class LookupPath
+ attr_reader :serverless_domain
+
+ delegate :serverless_domain_cluster, to: :serverless_domain
+ delegate :knative, to: :serverless_domain_cluster
+ delegate :certificate, to: :serverless_domain_cluster
+ delegate :key, to: :serverless_domain_cluster
+
+ def initialize(serverless_domain)
+ @serverless_domain = serverless_domain
+ end
+
+ def source
+ {
+ type: 'serverless',
+ service: serverless_domain.knative_uri.host,
+ cluster: {
+ hostname: knative.hostname,
+ address: knative.external_ip,
+ port: 443,
+ cert: certificate,
+ key: key
+ }
+ }
+ end
+ end
+end
diff --git a/app/models/serverless/virtual_domain.rb b/app/models/serverless/virtual_domain.rb
new file mode 100644
index 00000000000..d6a23a4c0ce
--- /dev/null
+++ b/app/models/serverless/virtual_domain.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module Serverless
+ class VirtualDomain
+ attr_reader :serverless_domain
+
+ delegate :serverless_domain_cluster, to: :serverless_domain
+ delegate :pages_domain, to: :serverless_domain_cluster
+ delegate :certificate, to: :pages_domain
+ delegate :key, to: :pages_domain
+
+ def initialize(serverless_domain)
+ @serverless_domain = serverless_domain
+ end
+
+ def lookup_paths
+ [
+ ::Serverless::LookupPath.new(serverless_domain)
+ ]
+ end
+ end
+end
diff --git a/app/services/ci/register_job_service.rb b/app/services/ci/register_job_service.rb
index 57c0cdd0602..fb59797a8df 100644
--- a/app/services/ci/register_job_service.rb
+++ b/app/services/ci/register_job_service.rb
@@ -8,6 +8,8 @@ module Ci
JOB_QUEUE_DURATION_SECONDS_BUCKETS = [1, 3, 10, 30, 60, 300, 900, 1800, 3600].freeze
JOBS_RUNNING_FOR_PROJECT_MAX_BUCKET = 5.freeze
+ METRICS_SHARD_TAG_PREFIX = 'metrics_shard::'.freeze
+ DEFAULT_METRICS_SHARD = 'default'.freeze
Result = Struct.new(:build, :valid?)
@@ -193,7 +195,13 @@ module Ci
def register_success(job)
labels = { shared_runner: runner.instance_type?,
- jobs_running_for_project: jobs_running_for_project(job) }
+ jobs_running_for_project: jobs_running_for_project(job),
+ shard: DEFAULT_METRICS_SHARD }
+
+ if runner.instance_type?
+ shard = runner.tag_list.sort.find { |name| name.starts_with?(METRICS_SHARD_TAG_PREFIX) }
+ labels[:shard] = shard.gsub(METRICS_SHARD_TAG_PREFIX, '') if shard
+ end
job_queue_duration_seconds.observe(labels, Time.now - job.queued_at) unless job.queued_at.nil?
attempt_counter.increment
diff --git a/app/views/discussions/_resolve_all.html.haml b/app/views/discussions/_resolve_all.html.haml
deleted file mode 100644
index 689a22acd27..00000000000
--- a/app/views/discussions/_resolve_all.html.haml
+++ /dev/null
@@ -1,8 +0,0 @@
-%resolve-discussion-btn{ ":discussion-id" => "'#{discussion.id}'",
- ":merge-request-id" => discussion.noteable.iid,
- ":can-resolve" => discussion.can_resolve?(current_user),
- "inline-template" => true }
- .btn-group{ role: "group", "v-if" => "showButton" }
- %button.btn.btn-default{ type: "button", "@click" => "resolve", ":disabled" => "loading", "v-cloak" => "true" }
- = icon("spinner spin", "v-show" => "loading")
- {{ buttonText }}
diff --git a/app/views/shared/issuable/_search_bar.html.haml b/app/views/shared/issuable/_search_bar.html.haml
index a27ceaff782..d9ca0b8869f 100644
--- a/app/views/shared/issuable/_search_bar.html.haml
+++ b/app/views/shared/issuable/_search_bar.html.haml
@@ -159,6 +159,8 @@
= render_if_exists 'shared/issuable/filter_weight', type: type
+ = render_if_exists 'shared/issuable/filter_epic', type: type
+
%button.clear-search.hidden{ type: 'button' }
= icon('times')
.filter-dropdown-container.d-flex.flex-column.flex-md-row