summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-02-24 18:09:05 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-02-24 18:09:05 +0000
commitc2367afbf57ebc65d5b78a743b5d6a91f0aece9f (patch)
tree165c2c54bf72ab3a3a9417d97f63ece5c9eba9f5 /app
parent51a9512965d86e3094968fa514e4ae8a96d38cf3 (diff)
downloadgitlab-ce-c2367afbf57ebc65d5b78a743b5d6a91f0aece9f.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/grafana_integration/components/grafana_integration.vue4
-rw-r--r--app/assets/javascripts/operation_settings/components/external_dashboard.vue4
-rw-r--r--app/assets/javascripts/pages/projects/pipelines/init_pipelines.js28
-rw-r--r--app/assets/javascripts/pages/projects/settings/integrations/show/index.js6
-rw-r--r--app/assets/javascripts/pipelines/pipeline_details_bundle.js8
-rw-r--r--app/assets/javascripts/releases/components/app_index.vue2
-rw-r--r--app/assets/javascripts/releases/components/evidence_block.vue6
-rw-r--r--app/assets/javascripts/releases/components/release_block.vue14
-rw-r--r--app/assets/javascripts/releases/components/release_block_author.vue4
-rw-r--r--app/assets/javascripts/releases/components/release_block_footer.vue8
-rw-r--r--app/assets/javascripts/releases/components/release_block_header.vue6
-rw-r--r--app/assets/javascripts/releases/components/release_block_metadata.vue16
-rw-r--r--app/assets/javascripts/releases/components/release_block_milestone_info.vue4
-rw-r--r--app/assets/javascripts/releases/components/release_block_milestones.vue2
-rw-r--r--app/assets/javascripts/releases/stores/modules/detail/actions.js3
-rw-r--r--app/assets/javascripts/releases/stores/modules/list/actions.js12
-rw-r--r--app/controllers/projects/hooks_controller.rb11
-rw-r--r--app/controllers/projects/settings/integrations_controller.rb4
-rw-r--r--app/graphql/resolvers/boards_resolver.rb18
-rw-r--r--app/graphql/types/group_type.rb6
-rw-r--r--app/graphql/types/project_type.rb6
-rw-r--r--app/helpers/projects_helper.rb3
-rw-r--r--app/helpers/user_callouts_helper.rb5
-rw-r--r--app/models/hooks/project_hook.rb2
-rw-r--r--app/models/user_callout_enums.rb3
-rw-r--r--app/services/resource_events/change_milestone_service.rb42
-rw-r--r--app/views/layouts/nav/sidebar/_project.html.haml6
-rw-r--r--app/views/projects/hook_logs/show.html.haml4
-rw-r--r--app/views/projects/hooks/edit.html.haml5
-rw-r--r--app/views/projects/hooks/index.html.haml (renamed from app/views/projects/hooks/_index.html.haml)4
-rw-r--r--app/views/projects/services/_index.html.haml6
-rw-r--r--app/views/projects/services/edit.html.haml3
-rw-r--r--app/views/projects/settings/integrations/show.html.haml14
-rw-r--r--app/views/projects/settings/operations/_error_tracking.html.haml2
-rw-r--r--app/views/projects/settings/operations/_incidents.html.haml2
-rw-r--r--app/views/shared/web_hooks/_form.html.haml22
36 files changed, 175 insertions, 120 deletions
diff --git a/app/assets/javascripts/grafana_integration/components/grafana_integration.vue b/app/assets/javascripts/grafana_integration/components/grafana_integration.vue
index 41d83e45c52..22cafd50bf3 100644
--- a/app/assets/javascripts/grafana_integration/components/grafana_integration.vue
+++ b/app/assets/javascripts/grafana_integration/components/grafana_integration.vue
@@ -55,9 +55,9 @@ export default {
<template>
<section id="grafana" class="settings no-animate js-grafana-integration">
<div class="settings-header">
- <h4 class="js-section-header">
+ <h3 class="js-section-header h4">
{{ s__('GrafanaIntegration|Grafana Authentication') }}
- </h4>
+ </h3>
<gl-button class="js-settings-toggle">{{ __('Expand') }}</gl-button>
<p class="js-section-sub-header">
{{ s__('GrafanaIntegration|Embed Grafana charts in GitLab issues.') }}
diff --git a/app/assets/javascripts/operation_settings/components/external_dashboard.vue b/app/assets/javascripts/operation_settings/components/external_dashboard.vue
index e90e27a402a..8b6467bc0f6 100644
--- a/app/assets/javascripts/operation_settings/components/external_dashboard.vue
+++ b/app/assets/javascripts/operation_settings/components/external_dashboard.vue
@@ -33,9 +33,9 @@ export default {
<template>
<section class="settings no-animate">
<div class="settings-header">
- <h4 class="js-section-header">
+ <h3 class="js-section-header h4">
{{ s__('ExternalMetrics|External Dashboard') }}
- </h4>
+ </h3>
<gl-button class="js-settings-toggle">{{ __('Expand') }}</gl-button>
<p class="js-section-sub-header">
{{
diff --git a/app/assets/javascripts/pages/projects/pipelines/init_pipelines.js b/app/assets/javascripts/pages/projects/pipelines/init_pipelines.js
index ade6908c4a5..5fd3fce88aa 100644
--- a/app/assets/javascripts/pages/projects/pipelines/init_pipelines.js
+++ b/app/assets/javascripts/pages/projects/pipelines/init_pipelines.js
@@ -13,19 +13,21 @@ export default () => {
});
}
+ const pipelineTabLink = document.querySelector('.js-pipeline-tab-link a');
const { controllerAction } = document.querySelector('.js-pipeline-container').dataset;
- const pipelineStatusUrl = `${document
- .querySelector('.js-pipeline-tab-link a')
- .getAttribute('href')}/status.json`;
- // eslint-disable-next-line no-new
- new Pipelines({
- initTabs: true,
- pipelineStatusUrl,
- tabsOptions: {
- action: controllerAction,
- defaultAction: 'pipelines',
- parentEl: '.pipelines-tabs',
- },
- });
+ if (pipelineTabLink) {
+ const pipelineStatusUrl = `${pipelineTabLink.getAttribute('href')}/status.json`;
+
+ // eslint-disable-next-line no-new
+ new Pipelines({
+ initTabs: true,
+ pipelineStatusUrl,
+ tabsOptions: {
+ action: controllerAction,
+ defaultAction: 'pipelines',
+ parentEl: '.pipelines-tabs',
+ },
+ });
+ }
};
diff --git a/app/assets/javascripts/pages/projects/settings/integrations/show/index.js b/app/assets/javascripts/pages/projects/settings/integrations/show/index.js
new file mode 100644
index 00000000000..f2cf2eb9b28
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/settings/integrations/show/index.js
@@ -0,0 +1,6 @@
+import PersistentUserCallout from '~/persistent_user_callout';
+
+document.addEventListener('DOMContentLoaded', () => {
+ const callout = document.querySelector('.js-webhooks-moved-alert');
+ PersistentUserCallout.factory(callout);
+});
diff --git a/app/assets/javascripts/pipelines/pipeline_details_bundle.js b/app/assets/javascripts/pipelines/pipeline_details_bundle.js
index d9192d3d76b..ffcb0f24cc6 100644
--- a/app/assets/javascripts/pipelines/pipeline_details_bundle.js
+++ b/app/assets/javascripts/pipelines/pipeline_details_bundle.js
@@ -95,14 +95,14 @@ export default () => {
},
});
+ const tabsElement = document.querySelector('.pipelines-tabs');
const testReportsEnabled =
window.gon && window.gon.features && window.gon.features.junitPipelineView;
- if (testReportsEnabled) {
+ if (tabsElement && testReportsEnabled) {
const fetchReportsAction = 'fetchReports';
testReportsStore.dispatch('setEndpoint', dataset.testReportEndpoint);
- const tabsElmement = document.querySelector('.pipelines-tabs');
const isTestTabActive = Boolean(
document.querySelector('.pipelines-tabs > li > a.test-tab.active'),
);
@@ -113,11 +113,11 @@ export default () => {
const tabClickHandler = e => {
if (e.target.className === 'test-tab') {
testReportsStore.dispatch(fetchReportsAction);
- tabsElmement.removeEventListener('click', tabClickHandler);
+ tabsElement.removeEventListener('click', tabClickHandler);
}
};
- tabsElmement.addEventListener('click', tabClickHandler);
+ tabsElement.addEventListener('click', tabClickHandler);
}
// eslint-disable-next-line no-new
diff --git a/app/assets/javascripts/releases/components/app_index.vue b/app/assets/javascripts/releases/components/app_index.vue
index f602c9fdda2..b9e80899e25 100644
--- a/app/assets/javascripts/releases/components/app_index.vue
+++ b/app/assets/javascripts/releases/components/app_index.vue
@@ -76,7 +76,7 @@ export default {
<div v-else-if="shouldRenderSuccessState" class="js-success-state">
<release-block
v-for="(release, index) in releases"
- :key="release.tag_name"
+ :key="release.tagName"
:release="release"
:class="{ 'linked-card': releases.length > 1 && index !== releases.length - 1 }"
/>
diff --git a/app/assets/javascripts/releases/components/evidence_block.vue b/app/assets/javascripts/releases/components/evidence_block.vue
index d9abd195fee..edbea33f1d1 100644
--- a/app/assets/javascripts/releases/components/evidence_block.vue
+++ b/app/assets/javascripts/releases/components/evidence_block.vue
@@ -25,16 +25,16 @@ export default {
},
computed: {
evidenceTitle() {
- return sprintf(__('%{tag}-evidence.json'), { tag: this.release.tag_name });
+ return sprintf(__('%{tag}-evidence.json'), { tag: this.release.tagName });
},
evidenceUrl() {
- return this.release.assets && this.release.assets.evidence_file_path;
+ return this.release.assets && this.release.assets.evidenceFilePath;
},
shortSha() {
return truncateSha(this.sha);
},
sha() {
- return this.release.evidence_sha;
+ return this.release.evidenceSha;
},
},
};
diff --git a/app/assets/javascripts/releases/components/release_block.vue b/app/assets/javascripts/releases/components/release_block.vue
index bc3f2c3bf30..f2cc36e38bb 100644
--- a/app/assets/javascripts/releases/components/release_block.vue
+++ b/app/assets/javascripts/releases/components/release_block.vue
@@ -38,13 +38,13 @@ export default {
},
computed: {
id() {
- return slugify(this.release.tag_name);
+ return slugify(this.release.tagName);
},
assets() {
return this.release.assets || {};
},
hasEvidence() {
- return Boolean(this.release.evidence_sha);
+ return Boolean(this.release.evidenceSha);
},
milestones() {
return this.release.milestones || [];
@@ -102,7 +102,7 @@ export default {
<evidence-block v-if="hasEvidence && shouldShowEvidence" :release="release" />
<div ref="gfm-content" class="card-text prepend-top-default">
- <div v-html="release.description_html"></div>
+ <div v-html="release.descriptionHtml"></div>
</div>
</div>
@@ -110,11 +110,11 @@ export default {
v-if="shouldShowFooter"
class="card-footer"
:commit="release.commit"
- :commit-path="release.commit_path"
- :tag-name="release.tag_name"
- :tag-path="release.tag_path"
+ :commit-path="release.commitPath"
+ :tag-name="release.tagName"
+ :tag-path="release.tagPath"
:author="release.author"
- :released-at="release.released_at"
+ :released-at="release.releasedAt"
/>
</div>
</template>
diff --git a/app/assets/javascripts/releases/components/release_block_author.vue b/app/assets/javascripts/releases/components/release_block_author.vue
index e7075d4d67a..0432d45b2dc 100644
--- a/app/assets/javascripts/releases/components/release_block_author.vue
+++ b/app/assets/javascripts/releases/components/release_block_author.vue
@@ -31,8 +31,8 @@ export default {
<template #user>
<user-avatar-link
class="prepend-left-4"
- :link-href="author.web_url"
- :img-src="author.avatar_url"
+ :link-href="author.webUrl"
+ :img-src="author.avatarUrl"
:img-alt="userImageAltDescription"
:tooltip-text="author.username"
/>
diff --git a/app/assets/javascripts/releases/components/release_block_footer.vue b/app/assets/javascripts/releases/components/release_block_footer.vue
index 8533fc17ffd..a95fbc0b373 100644
--- a/app/assets/javascripts/releases/components/release_block_footer.vue
+++ b/app/assets/javascripts/releases/components/release_block_footer.vue
@@ -66,9 +66,9 @@ export default {
<icon ref="commitIcon" name="commit" class="mr-1" />
<div v-gl-tooltip.bottom :title="commit.title">
<gl-link v-if="commitPath" :href="commitPath">
- {{ commit.short_id }}
+ {{ commit.shortId }}
</gl-link>
- <span v-else>{{ commit.short_id }}</span>
+ <span v-else>{{ commit.shortId }}</span>
</div>
</div>
@@ -100,8 +100,8 @@ export default {
<div v-if="author" class="d-flex">
<span class="text-secondary">{{ __('by') }}&nbsp;</span>
<user-avatar-link
- :link-href="author.web_url"
- :img-src="author.avatar_url"
+ :link-href="author.webUrl"
+ :img-src="author.avatarUrl"
:img-alt="userImageAltDescription"
:tooltip-text="author.username"
tooltip-placement="bottom"
diff --git a/app/assets/javascripts/releases/components/release_block_header.vue b/app/assets/javascripts/releases/components/release_block_header.vue
index b459418aef2..f0d3f3f8c1d 100644
--- a/app/assets/javascripts/releases/components/release_block_header.vue
+++ b/app/assets/javascripts/releases/components/release_block_header.vue
@@ -20,10 +20,10 @@ export default {
},
computed: {
editLink() {
- return this.release._links?.edit_url;
+ return this.release.Links?.editUrl;
},
selfLink() {
- return this.release._links?.self;
+ return this.release.Links?.self;
},
},
};
@@ -36,7 +36,7 @@ export default {
{{ release.name }}
</gl-link>
<template v-else>{{ release.name }}</template>
- <gl-badge v-if="release.upcoming_release" variant="warning" class="align-middle">{{
+ <gl-badge v-if="release.upcomingRelease" variant="warning" class="align-middle">{{
__('Upcoming Release')
}}</gl-badge>
</h2>
diff --git a/app/assets/javascripts/releases/components/release_block_metadata.vue b/app/assets/javascripts/releases/components/release_block_metadata.vue
index f0aad594062..052e4088a5f 100644
--- a/app/assets/javascripts/releases/components/release_block_metadata.vue
+++ b/app/assets/javascripts/releases/components/release_block_metadata.vue
@@ -32,21 +32,21 @@ export default {
return this.release.commit || {};
},
commitUrl() {
- return this.release.commit_path;
+ return this.release.commitPath;
},
hasAuthor() {
return Boolean(this.author);
},
releasedTimeAgo() {
return sprintf(__('released %{time}'), {
- time: this.timeFormatted(this.release.released_at),
+ time: this.timeFormatted(this.release.releasedAt),
});
},
shouldRenderMilestones() {
return Boolean(this.release.milestones?.length);
},
tagUrl() {
- return this.release.tag_path;
+ return this.release.tagPath;
},
},
};
@@ -57,24 +57,24 @@ export default {
<div class="append-right-8">
<icon name="commit" class="align-middle" />
<gl-link v-if="commitUrl" v-gl-tooltip.bottom :title="commit.title" :href="commitUrl">
- {{ commit.short_id }}
+ {{ commit.shortId }}
</gl-link>
- <span v-else v-gl-tooltip.bottom :title="commit.title">{{ commit.short_id }}</span>
+ <span v-else v-gl-tooltip.bottom :title="commit.title">{{ commit.shortId }}</span>
</div>
<div class="append-right-8">
<icon name="tag" class="align-middle" />
<gl-link v-if="tagUrl" v-gl-tooltip.bottom :title="__('Tag')" :href="tagUrl">
- {{ release.tag_name }}
+ {{ release.tagName }}
</gl-link>
- <span v-else v-gl-tooltip.bottom :title="__('Tag')">{{ release.tag_name }}</span>
+ <span v-else v-gl-tooltip.bottom :title="__('Tag')">{{ release.tagName }}</span>
</div>
<release-block-milestones v-if="shouldRenderMilestones" :milestones="release.milestones" />
<div class="append-right-4">
&bull;
- <span v-gl-tooltip.bottom :title="tooltipTitle(release.released_at)">
+ <span v-gl-tooltip.bottom :title="tooltipTitle(release.releasedAt)">
{{ releasedTimeAgo }}
</span>
</div>
diff --git a/app/assets/javascripts/releases/components/release_block_milestone_info.vue b/app/assets/javascripts/releases/components/release_block_milestone_info.vue
index d3e354d6157..50accf6b679 100644
--- a/app/assets/javascripts/releases/components/release_block_milestone_info.vue
+++ b/app/assets/javascripts/releases/components/release_block_milestone_info.vue
@@ -40,7 +40,7 @@ export default {
return Number.isNaN(percent) ? 0 : percent;
},
allIssueStats() {
- return this.milestones.map(m => m.issue_stats || {});
+ return this.milestones.map(m => m.issueStats || {});
},
openIssuesCount() {
return this.allIssueStats.map(stats => stats.opened || 0).reduce(sumReducer);
@@ -109,7 +109,7 @@ export default {
:key="milestone.id"
v-gl-tooltip
:title="milestone.description"
- :href="milestone.web_url"
+ :href="milestone.webUrl"
class="append-right-4"
>
{{ milestone.title }}
diff --git a/app/assets/javascripts/releases/components/release_block_milestones.vue b/app/assets/javascripts/releases/components/release_block_milestones.vue
index a3dff75b828..9abd3345b22 100644
--- a/app/assets/javascripts/releases/components/release_block_milestones.vue
+++ b/app/assets/javascripts/releases/components/release_block_milestones.vue
@@ -38,7 +38,7 @@ export default {
:key="milestone.id"
v-gl-tooltip
:title="milestone.description"
- :href="milestone.web_url"
+ :href="milestone.webUrl"
class="mx-1 js-milestone-link"
>
{{ milestone.title }}
diff --git a/app/assets/javascripts/releases/stores/modules/detail/actions.js b/app/assets/javascripts/releases/stores/modules/detail/actions.js
index c9749582f5c..f730af1c7dc 100644
--- a/app/assets/javascripts/releases/stores/modules/detail/actions.js
+++ b/app/assets/javascripts/releases/stores/modules/detail/actions.js
@@ -22,8 +22,7 @@ export const fetchRelease = ({ dispatch, state }) => {
return api
.release(state.projectId, state.tagName)
.then(({ data: release }) => {
- const camelCasedRelease = convertObjectPropsToCamelCase(release, { deep: true });
- dispatch('receiveReleaseSuccess', camelCasedRelease);
+ dispatch('receiveReleaseSuccess', convertObjectPropsToCamelCase(release, { deep: true }));
})
.catch(error => {
dispatch('receiveReleaseError', error);
diff --git a/app/assets/javascripts/releases/stores/modules/list/actions.js b/app/assets/javascripts/releases/stores/modules/list/actions.js
index b15fb69226f..06d13890a9d 100644
--- a/app/assets/javascripts/releases/stores/modules/list/actions.js
+++ b/app/assets/javascripts/releases/stores/modules/list/actions.js
@@ -2,7 +2,11 @@ import * as types from './mutation_types';
import createFlash from '~/flash';
import { __ } from '~/locale';
import api from '~/api';
-import { normalizeHeaders, parseIntPagination } from '~/lib/utils/common_utils';
+import {
+ normalizeHeaders,
+ parseIntPagination,
+ convertObjectPropsToCamelCase,
+} from '~/lib/utils/common_utils';
/**
* Commits a mutation to update the state while the main endpoint is being requested.
@@ -28,7 +32,11 @@ export const fetchReleases = ({ dispatch }, { page = '1', projectId }) => {
export const receiveReleasesSuccess = ({ commit }, { data, headers }) => {
const pageInfo = parseIntPagination(normalizeHeaders(headers));
- commit(types.RECEIVE_RELEASES_SUCCESS, { data, pageInfo });
+ const camelCasedReleases = convertObjectPropsToCamelCase(data, { deep: true });
+ commit(types.RECEIVE_RELEASES_SUCCESS, {
+ data: camelCasedReleases,
+ pageInfo,
+ });
};
export const receiveReleasesError = ({ commit }) => {
diff --git a/app/controllers/projects/hooks_controller.rb b/app/controllers/projects/hooks_controller.rb
index 5fa0339f44d..097a357889f 100644
--- a/app/controllers/projects/hooks_controller.rb
+++ b/app/controllers/projects/hooks_controller.rb
@@ -12,7 +12,8 @@ class Projects::HooksController < Projects::ApplicationController
layout "project_settings"
def index
- redirect_to project_settings_integrations_path(@project)
+ @hooks = @project.hooks
+ @hook = ProjectHook.new
end
def create
@@ -24,7 +25,7 @@ class Projects::HooksController < Projects::ApplicationController
flash[:alert] = @hook.errors.full_messages.join.html_safe
end
- redirect_to project_settings_integrations_path(@project)
+ redirect_to action: :index
end
def edit
@@ -33,7 +34,7 @@ class Projects::HooksController < Projects::ApplicationController
def update
if hook.update(hook_params)
flash[:notice] = _('Hook was successfully updated.')
- redirect_to project_settings_integrations_path(@project)
+ redirect_to action: :index
else
render 'edit'
end
@@ -44,13 +45,13 @@ class Projects::HooksController < Projects::ApplicationController
set_hook_execution_notice(result)
- redirect_back_or_default(default: { action: 'index' })
+ redirect_back_or_default(default: { action: :index })
end
def destroy
hook.destroy
- redirect_to project_settings_integrations_path(@project), status: :found
+ redirect_to action: :index, status: :found
end
private
diff --git a/app/controllers/projects/settings/integrations_controller.rb b/app/controllers/projects/settings/integrations_controller.rb
index 0c5cf01d912..a4a53676ec7 100644
--- a/app/controllers/projects/settings/integrations_controller.rb
+++ b/app/controllers/projects/settings/integrations_controller.rb
@@ -9,10 +9,6 @@ module Projects
layout "project_settings"
def show
- @hooks = @project.hooks
- @hook = ProjectHook.new
-
- # Services
@services = @project.find_or_initialize_services(exceptions: service_exceptions)
end
diff --git a/app/graphql/resolvers/boards_resolver.rb b/app/graphql/resolvers/boards_resolver.rb
index 45c03bf0bef..eceb5b38031 100644
--- a/app/graphql/resolvers/boards_resolver.rb
+++ b/app/graphql/resolvers/boards_resolver.rb
@@ -4,7 +4,11 @@ module Resolvers
class BoardsResolver < BaseResolver
type Types::BoardType, null: true
- def resolve(**args)
+ argument :id, GraphQL::ID_TYPE,
+ required: false,
+ description: 'Find a board by its ID'
+
+ def resolve(id: nil)
# The project or group could have been loaded in batch by `BatchLoader`.
# At this point we need the `id` of the project/group to query for boards, so
# make sure it's loaded and not `nil` before continuing.
@@ -12,7 +16,17 @@ module Resolvers
return Board.none unless parent
- Boards::ListService.new(parent, context[:current_user]).execute(create_default_board: false)
+ Boards::ListService.new(parent, context[:current_user], board_id: extract_board_id(id)).execute(create_default_board: false)
+ rescue ActiveRecord::RecordNotFound
+ Board.none
+ end
+
+ private
+
+ def extract_board_id(gid)
+ return unless gid.present?
+
+ GitlabSchema.parse_gid(gid, expected_type: ::Board).model_id
end
end
end
diff --git a/app/graphql/types/group_type.rb b/app/graphql/types/group_type.rb
index 9f3905000b2..699aa51e6c8 100644
--- a/app/graphql/types/group_type.rb
+++ b/app/graphql/types/group_type.rb
@@ -52,6 +52,12 @@ module Types
null: true,
description: 'Boards of the group',
resolver: Resolvers::BoardsResolver
+
+ field :board,
+ Types::BoardType,
+ null: true,
+ description: 'A single board of the group',
+ resolver: Resolvers::BoardsResolver.single
end
end
diff --git a/app/graphql/types/project_type.rb b/app/graphql/types/project_type.rb
index f89bd5575a3..1142459f6eb 100644
--- a/app/graphql/types/project_type.rb
+++ b/app/graphql/types/project_type.rb
@@ -185,6 +185,12 @@ module Types
null: true,
description: 'Boards of the project',
resolver: Resolvers::BoardsResolver
+
+ field :board,
+ Types::BoardType,
+ null: true,
+ description: 'A single board of the project',
+ resolver: Resolvers::BoardsResolver.single
end
end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 5aff12621b5..cf9f3b9e924 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -669,6 +669,9 @@ module ProjectsHelper
project_members#index
integrations#show
services#edit
+ hooks#index
+ hooks#edit
+ hook_logs#show
repository#show
ci_cd#show
operations#show
diff --git a/app/helpers/user_callouts_helper.rb b/app/helpers/user_callouts_helper.rb
index ab691916706..841599abe81 100644
--- a/app/helpers/user_callouts_helper.rb
+++ b/app/helpers/user_callouts_helper.rb
@@ -5,6 +5,7 @@ module UserCalloutsHelper
GCP_SIGNUP_OFFER = 'gcp_signup_offer'
SUGGEST_POPOVER_DISMISSED = 'suggest_popover_dismissed'
TABS_POSITION_HIGHLIGHT = 'tabs_position_highlight'
+ WEBHOOKS_MOVED = 'webhooks_moved'
def show_gke_cluster_integration_callout?(project)
can?(current_user, :create_cluster, project) &&
@@ -33,6 +34,10 @@ module UserCalloutsHelper
current_user && !user_dismissed?(TABS_POSITION_HIGHLIGHT) && !Rails.env.test?
end
+ def show_webhooks_moved_alert?
+ !user_dismissed?(WEBHOOKS_MOVED)
+ end
+
private
def user_dismissed?(feature_name, ignore_dismissal_earlier_than = nil)
diff --git a/app/models/hooks/project_hook.rb b/app/models/hooks/project_hook.rb
index a5f68831f34..bc480b14e67 100644
--- a/app/models/hooks/project_hook.rb
+++ b/app/models/hooks/project_hook.rb
@@ -21,7 +21,7 @@ class ProjectHook < WebHook
validates :project, presence: true
def pluralized_name
- _('Project Hooks')
+ _('Webhooks')
end
end
diff --git a/app/models/user_callout_enums.rb b/app/models/user_callout_enums.rb
index ef0b2407e23..625cbb4fe5f 100644
--- a/app/models/user_callout_enums.rb
+++ b/app/models/user_callout_enums.rb
@@ -15,7 +15,8 @@ module UserCalloutEnums
gcp_signup_offer: 2,
cluster_security_warning: 3,
suggest_popover_dismissed: 9,
- tabs_position_highlight: 10
+ tabs_position_highlight: 10,
+ webhooks_moved: 13
}
end
end
diff --git a/app/services/resource_events/change_milestone_service.rb b/app/services/resource_events/change_milestone_service.rb
index bad7d002c65..dd637bcc765 100644
--- a/app/services/resource_events/change_milestone_service.rb
+++ b/app/services/resource_events/change_milestone_service.rb
@@ -2,49 +2,35 @@
module ResourceEvents
class ChangeMilestoneService
- attr_reader :resource, :user, :event_created_at, :resource_args
+ attr_reader :resource, :user, :event_created_at, :milestone
def initialize(resource:, user:, created_at: Time.now)
@resource = resource
@user = user
@event_created_at = created_at
-
- @resource_args = {
- user_id: user.id,
- created_at: event_created_at
- }
+ @milestone = resource&.milestone
end
def execute
- args = build_resource_args
-
- action = if milestone.nil?
- :remove
- else
- :add
- end
+ ResourceMilestoneEvent.create(build_resource_args)
- record = args.merge(milestone_id: milestone&.id, action: ResourceMilestoneEvent.actions[action])
-
- create_event(record)
+ resource.expire_note_etag_cache
end
private
- def milestone
- resource&.milestone
- end
-
- def create_event(record)
- ResourceMilestoneEvent.create(record)
-
- resource.expire_note_etag_cache
- end
-
def build_resource_args
- key = resource.class.name.underscore.foreign_key
+ action = milestone.blank? ? :remove : :add
+ key = resource.class.name.foreign_key
- resource_args.merge(key => resource.id, state: ResourceMilestoneEvent.states[resource.state])
+ {
+ user_id: user.id,
+ created_at: event_created_at,
+ milestone_id: milestone&.id,
+ state: ResourceMilestoneEvent.states[resource.state],
+ action: ResourceMilestoneEvent.actions[action],
+ key => resource.id
+ }
end
end
end
diff --git a/app/views/layouts/nav/sidebar/_project.html.haml b/app/views/layouts/nav/sidebar/_project.html.haml
index b9324f0596c..160e2a7c952 100644
--- a/app/views/layouts/nav/sidebar/_project.html.haml
+++ b/app/views/layouts/nav/sidebar/_project.html.haml
@@ -366,10 +366,14 @@
%span
= _('Members')
- if can_edit
- = nav_link(controller: [:integrations, :services, :hooks, :hook_logs]) do
+ = nav_link(controller: [:integrations, :services]) do
= link_to project_settings_integrations_path(@project), title: _('Integrations'), data: { qa_selector: 'integrations_settings_link' } do
%span
= _('Integrations')
+ = nav_link(controller: [:hooks, :hook_logs]) do
+ = link_to project_hooks_path(@project), title: _('Webhooks'), data: { qa_selector: 'webhooks_settings_link' } do
+ %span
+ = _('Webhooks')
= nav_link(controller: :repository) do
= link_to project_settings_repository_path(@project), title: _('Repository') do
%span
diff --git a/app/views/projects/hook_logs/show.html.haml b/app/views/projects/hook_logs/show.html.haml
index a8796cd7b1c..873fb4d47b7 100644
--- a/app/views/projects/hook_logs/show.html.haml
+++ b/app/views/projects/hook_logs/show.html.haml
@@ -1,3 +1,7 @@
+- @content_class = 'limit-container-width' unless fluid_layout
+- add_to_breadcrumbs _('Webhook Settings'), namespace_project_hooks_path
+- page_title _('Webhook Logs')
+
.row.prepend-top-default.append-bottom-default
.col-lg-3
%h4.prepend-top-0
diff --git a/app/views/projects/hooks/edit.html.haml b/app/views/projects/hooks/edit.html.haml
index c1fdf619eb5..f7eae802dac 100644
--- a/app/views/projects/hooks/edit.html.haml
+++ b/app/views/projects/hooks/edit.html.haml
@@ -1,5 +1,6 @@
-- add_to_breadcrumbs _('ProjectService|Integrations'), namespace_project_settings_integrations_path
-- page_title _('Edit Project Hook')
+- @content_class = 'limit-container-width' unless fluid_layout
+- add_to_breadcrumbs _('Webhook Settings'), namespace_project_hooks_path
+- page_title _('Webhook')
.row.prepend-top-default
.col-lg-3
diff --git a/app/views/projects/hooks/_index.html.haml b/app/views/projects/hooks/index.html.haml
index 70f2fa0e758..169a5cc9d6b 100644
--- a/app/views/projects/hooks/_index.html.haml
+++ b/app/views/projects/hooks/index.html.haml
@@ -1,3 +1,7 @@
+- @content_class = 'limit-container-width' unless fluid_layout
+- breadcrumb_title _('Webhook Settings')
+- page_title _('Webhooks')
+
.row.prepend-top-default
.col-lg-4
= render 'shared/web_hooks/title_and_docs', hook: @hook
diff --git a/app/views/projects/services/_index.html.haml b/app/views/projects/services/_index.html.haml
index 3f33d72d3ec..a4041d09415 100644
--- a/app/views/projects/services/_index.html.haml
+++ b/app/views/projects/services/_index.html.haml
@@ -1,8 +1,8 @@
-.row.prepend-top-default.append-bottom-default
+.row.prepend-top-default
.col-lg-4
%h4.prepend-top-0
- = s_("ProjectService|Project services")
- %p= s_("ProjectService|Project services allow you to integrate GitLab with other applications")
+ = _('Integrations')
+ %p= _('Integrations allow you to integrate GitLab with other applications')
.col-lg-8
%table.table
%colgroup
diff --git a/app/views/projects/services/edit.html.haml b/app/views/projects/services/edit.html.haml
index e3e8a312431..ef799d2c046 100644
--- a/app/views/projects/services/edit.html.haml
+++ b/app/views/projects/services/edit.html.haml
@@ -1,7 +1,6 @@
- breadcrumb_title @service.title
+- add_to_breadcrumbs _('Integration Settings'), project_settings_integrations_path(@project)
- page_title @service.title, s_("ProjectService|Services")
-- add_to_breadcrumbs(s_("ProjectService|Settings"), edit_project_path(@project))
-- add_to_breadcrumbs(s_("ProjectService|Integrations"), project_settings_integrations_path(@project))
= render 'deprecated_message' if @service.deprecation_message
diff --git a/app/views/projects/settings/integrations/show.html.haml b/app/views/projects/settings/integrations/show.html.haml
index 76770290f36..f603f23a2c7 100644
--- a/app/views/projects/settings/integrations/show.html.haml
+++ b/app/views/projects/settings/integrations/show.html.haml
@@ -1,5 +1,15 @@
- @content_class = "limit-container-width" unless fluid_layout
-- breadcrumb_title _("Integrations Settings")
+- breadcrumb_title _('Integration Settings')
- page_title _('Integrations')
-= render 'projects/hooks/index'
+
+- if show_webhooks_moved_alert?
+ .gl-alert.gl-alert-info.js-webhooks-moved-alert.prepend-top-default{ role: 'alert', data: { feature_id: UserCalloutsHelper::WEBHOOKS_MOVED, dismiss_endpoint: user_callouts_path } }
+ = sprite_icon('information-o', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
+ %button.js-close.gl-alert-dismiss{ type: 'button', 'aria-label' => _('Dismiss') }
+ = sprite_icon('close', size: 16, css_class: 'gl-icon')
+ .gl-alert-body
+ = _('Webhooks have moved. They can now be found under the Settings menu.')
+ .gl-alert-actions
+ = link_to _('Go to Webhooks'), project_hooks_path(@project), class: 'btn gl-alert-action btn-info new-gl-button'
+
= render 'projects/services/index'
diff --git a/app/views/projects/settings/operations/_error_tracking.html.haml b/app/views/projects/settings/operations/_error_tracking.html.haml
index 06b5243dfd9..393b1f9d21a 100644
--- a/app/views/projects/settings/operations/_error_tracking.html.haml
+++ b/app/views/projects/settings/operations/_error_tracking.html.haml
@@ -4,7 +4,7 @@
%section.settings.no-animate.js-error-tracking-settings
.settings-header
- %h4
+ %h3{ :class => "h4" }
= _('Error Tracking')
%button.btn.js-settings-toggle{ type: 'button' }
= _('Expand')
diff --git a/app/views/projects/settings/operations/_incidents.html.haml b/app/views/projects/settings/operations/_incidents.html.haml
index 756d4042613..a96a41b78c2 100644
--- a/app/views/projects/settings/operations/_incidents.html.haml
+++ b/app/views/projects/settings/operations/_incidents.html.haml
@@ -4,7 +4,7 @@
%section.settings.no-animate.qa-incident-management-settings
.settings-header
- %h4= _('Incidents')
+ %h3{ :class => "h4" }= _('Incidents')
%button.btn.js-settings-toggle{ type: 'button' }
= _('Expand')
%p
diff --git a/app/views/shared/web_hooks/_form.html.haml b/app/views/shared/web_hooks/_form.html.haml
index 9c5b9593bba..ce85cbd7f07 100644
--- a/app/views/shared/web_hooks/_form.html.haml
+++ b/app/views/shared/web_hooks/_form.html.haml
@@ -15,62 +15,62 @@
= form.check_box :push_events, class: 'form-check-input'
= form.label :push_events, class: 'list-label form-check-label ml-1' do
%strong Push events
- %p.light.ml-1
+ = form.text_field :push_events_branch_filter, class: 'form-control', placeholder: 'Branch name or wildcard pattern to trigger on (leave blank for all)'
+ %p.text-muted.ml-1
This URL will be triggered by a push to the repository
- = form.text_field :push_events_branch_filter, class: 'form-control', placeholder: 'Branch name or wildcard pattern to trigger on (leave blank for all)'
%li
= form.check_box :tag_push_events, class: 'form-check-input'
= form.label :tag_push_events, class: 'list-label form-check-label ml-1' do
%strong Tag push events
- %p.light.ml-1
+ %p.text-muted.ml-1
This URL will be triggered when a new tag is pushed to the repository
%li
= form.check_box :note_events, class: 'form-check-input'
= form.label :note_events, class: 'list-label form-check-label ml-1' do
%strong Comments
- %p.light.ml-1
+ %p.text-muted.ml-1
This URL will be triggered when someone adds a comment
%li
= form.check_box :confidential_note_events, class: 'form-check-input'
= form.label :confidential_note_events, class: 'list-label form-check-label ml-1' do
%strong Confidential Comments
- %p.light.ml-1
+ %p.text-muted.ml-1
This URL will be triggered when someone adds a comment on a confidential issue
%li
= form.check_box :issues_events, class: 'form-check-input'
= form.label :issues_events, class: 'list-label form-check-label ml-1' do
%strong Issues events
- %p.light.ml-1
+ %p.text-muted.ml-1
This URL will be triggered when an issue is created/updated/merged
%li
= form.check_box :confidential_issues_events, class: 'form-check-input'
= form.label :confidential_issues_events, class: 'list-label form-check-label ml-1' do
%strong Confidential Issues events
- %p.light.ml-1
+ %p.text-muted.ml-1
This URL will be triggered when a confidential issue is created/updated/merged
%li
= form.check_box :merge_requests_events, class: 'form-check-input'
= form.label :merge_requests_events, class: 'list-label form-check-label ml-1' do
%strong Merge request events
- %p.light.ml-1
+ %p.text-muted.ml-1
This URL will be triggered when a merge request is created/updated/merged
%li
= form.check_box :job_events, class: 'form-check-input'
= form.label :job_events, class: 'list-label form-check-label ml-1' do
%strong Job events
- %p.light.ml-1
+ %p.text-muted.ml-1
This URL will be triggered when the job status changes
%li
= form.check_box :pipeline_events, class: 'form-check-input'
= form.label :pipeline_events, class: 'list-label form-check-label ml-1' do
%strong Pipeline events
- %p.light.ml-1
+ %p.text-muted.ml-1
This URL will be triggered when the pipeline status changes
%li
= form.check_box :wiki_page_events, class: 'form-check-input'
= form.label :wiki_page_events, class: 'list-label form-check-label ml-1' do
%strong Wiki Page events
- %p.light.ml-1
+ %p.text-muted.ml-1
This URL will be triggered when a wiki page is created/updated
.form-group
= form.label :enable_ssl_verification, 'SSL verification', class: 'label-bold checkbox'