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
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-10-16 09:08:48 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-10-16 09:08:48 +0300
commite94d662e5aabd4918de373b37c4f084325c7c1f8 (patch)
tree0b2cfdcc08258329318dcbf4412266893f7616d6
parentc311ce331fcfe1c1f1619534eb746245a1deb326 (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--app/assets/javascripts/boards/filtered_search_boards.js3
-rw-r--r--app/assets/javascripts/jira_connect.js7
-rw-r--r--app/assets/javascripts/static_site_editor/graphql/index.js1
-rw-r--r--app/assets/javascripts/static_site_editor/graphql/resolvers/has_submitted_changes.js20
-rw-r--r--app/assets/javascripts/static_site_editor/graphql/resolvers/submit_content_changes.js15
-rw-r--r--app/assets/stylesheets/framework/tables.scss11
-rw-r--r--app/assets/stylesheets/page_bundles/_ide_theme_overrides.scss88
-rw-r--r--app/assets/stylesheets/page_bundles/ide_themes/_dark.scss12
-rw-r--r--app/assets/stylesheets/page_bundles/ide_themes/_solarized-dark.scss14
-rw-r--r--app/assets/stylesheets/page_bundles/jira_connect.scss77
-rw-r--r--app/assets/stylesheets/page_bundles/jira_connect_users.scss13
-rw-r--r--app/controllers/jira_connect/events_controller.rb4
-rw-r--r--app/controllers/jira_connect/users_controller.rb11
-rw-r--r--app/helpers/external_link_helper.rb2
-rw-r--r--app/views/jira_connect/subscriptions/index.html.haml92
-rw-r--r--app/views/jira_connect/users/show.html.haml12
-rw-r--r--changelogs/unreleased/229114-jira-connect-install-webhook-for-updates.yml5
-rw-r--r--changelogs/unreleased/235888-gitlab-for-jira-app-should-display-who-is-logged-in.yml5
-rw-r--r--config/application.rb1
-rw-r--r--config/feature_flags/development/global_default_branch_name.yml6
-rw-r--r--config/feature_flags/development/mr_commit_neighbor_nav.yml6
-rw-r--r--config/routes/jira_connect.rb1
-rw-r--r--doc/development/api_graphql_styleguide.md4
-rw-r--r--locale/gitlab.pot15
-rw-r--r--package.json2
-rw-r--r--spec/controllers/jira_connect/events_controller_spec.rb37
-rw-r--r--spec/frontend/static_site_editor/graphql/resolvers/has_submitted_changes_spec.js27
-rw-r--r--spec/helpers/external_link_helper_spec.rb11
-rw-r--r--spec/views/jira_connect/subscriptions/index.html.haml_spec.rb30
-rw-r--r--yarn.lock8
30 files changed, 451 insertions, 89 deletions
diff --git a/app/assets/javascripts/boards/filtered_search_boards.js b/app/assets/javascripts/boards/filtered_search_boards.js
index fff89832bf0..4fa78ecd5a4 100644
--- a/app/assets/javascripts/boards/filtered_search_boards.js
+++ b/app/assets/javascripts/boards/filtered_search_boards.js
@@ -25,7 +25,8 @@ export default class FilteredSearchBoards extends FilteredSearchManager {
}
updateObject(path) {
- this.store.path = path.substr(1);
+ const groupByParam = new URLSearchParams(window.location.search).get('group_by');
+ this.store.path = `${path.substr(1)}${groupByParam ? `&group_by=${groupByParam}` : ''}`;
if (gon.features.boardsWithSwimlanes || gon.features.graphqlBoardLists) {
boardsStore.updateFiltersUrl();
diff --git a/app/assets/javascripts/jira_connect.js b/app/assets/javascripts/jira_connect.js
index 895cdc4562c..0864a3024ac 100644
--- a/app/assets/javascripts/jira_connect.js
+++ b/app/assets/javascripts/jira_connect.js
@@ -18,6 +18,13 @@ function onLoaded() {
alert(res.responseJSON.error);
};
+ AP.getLocation(function(location) {
+ $('.js-jira-connect-sign-in').each(function() {
+ var updatedLink = `${$(this).attr('href')}?return_to=${location}`;
+ $(this).attr('href', updatedLink);
+ });
+ });
+
$('#add-subscription-form').on('submit', function(e) {
var actionUrl = $(this).attr('action');
e.preventDefault();
diff --git a/app/assets/javascripts/static_site_editor/graphql/index.js b/app/assets/javascripts/static_site_editor/graphql/index.js
index fbb3d7fbfcc..cc68bc57bb0 100644
--- a/app/assets/javascripts/static_site_editor/graphql/index.js
+++ b/app/assets/javascripts/static_site_editor/graphql/index.js
@@ -21,6 +21,7 @@ const createApolloProvider = appData => {
},
{
typeDefs,
+ assumeImmutableResults: true,
},
);
diff --git a/app/assets/javascripts/static_site_editor/graphql/resolvers/has_submitted_changes.js b/app/assets/javascripts/static_site_editor/graphql/resolvers/has_submitted_changes.js
index ce55db7f3e5..ea49b21eb0d 100644
--- a/app/assets/javascripts/static_site_editor/graphql/resolvers/has_submitted_changes.js
+++ b/app/assets/javascripts/static_site_editor/graphql/resolvers/has_submitted_changes.js
@@ -1,16 +1,24 @@
+import { produce } from 'immer';
import query from '../queries/app_data.query.graphql';
const hasSubmittedChangesResolver = (_, { input: { hasSubmittedChanges } }, { cache }) => {
- const { appData } = cache.readQuery({ query });
- cache.writeQuery({
- query,
- data: {
+ const oldData = cache.readQuery({ query });
+
+ const data = produce(oldData, draftState => {
+ // punctually modifying draftState as per immer docs upsets our linters
+ return {
+ ...draftState,
appData: {
__typename: 'AppData',
- ...appData,
+ ...draftState.appData,
hasSubmittedChanges,
},
- },
+ };
+ });
+
+ cache.writeQuery({
+ query,
+ data,
});
};
diff --git a/app/assets/javascripts/static_site_editor/graphql/resolvers/submit_content_changes.js b/app/assets/javascripts/static_site_editor/graphql/resolvers/submit_content_changes.js
index 694cf762e51..4137ede49c6 100644
--- a/app/assets/javascripts/static_site_editor/graphql/resolvers/submit_content_changes.js
+++ b/app/assets/javascripts/static_site_editor/graphql/resolvers/submit_content_changes.js
@@ -1,3 +1,4 @@
+import { produce } from 'immer';
import submitContentChanges from '../../services/submit_content_changes';
import savedContentMetaQuery from '../queries/saved_content_meta.query.graphql';
@@ -14,14 +15,18 @@ const submitContentChangesResolver = (
images,
mergeRequestMeta,
}).then(savedContentMeta => {
- cache.writeQuery({
- query: savedContentMetaQuery,
- data: {
+ const data = produce(savedContentMeta, draftState => {
+ return {
savedContentMeta: {
__typename: 'SavedContentMeta',
- ...savedContentMeta,
+ ...draftState,
},
- },
+ };
+ });
+
+ cache.writeQuery({
+ query: savedContentMetaQuery,
+ data,
});
});
};
diff --git a/app/assets/stylesheets/framework/tables.scss b/app/assets/stylesheets/framework/tables.scss
index 59e83608d9d..a8c830f5a42 100644
--- a/app/assets/stylesheets/framework/tables.scss
+++ b/app/assets/stylesheets/framework/tables.scss
@@ -186,6 +186,7 @@ table {
.checkbox {
padding-left: $gl-spacing-scale-4;
padding-right: 0;
+ width: 1px;
+ td,
+ th {
@@ -205,12 +206,20 @@ table {
width: 10%;
}
+ .description {
+ max-width: 0;
+ }
+
.identifier {
width: 16%;
}
.scanner {
- width: 15%;
+ width: 10%;
+ }
+
+ .activity {
+ width: 5%;
}
}
}
diff --git a/app/assets/stylesheets/page_bundles/_ide_theme_overrides.scss b/app/assets/stylesheets/page_bundles/_ide_theme_overrides.scss
index 93cb9be4a8f..d1f7c2e9865 100644
--- a/app/assets/stylesheets/page_bundles/_ide_theme_overrides.scss
+++ b/app/assets/stylesheets/page_bundles/_ide_theme_overrides.scss
@@ -226,20 +226,20 @@
@return calc(#{$original-padding + $original-border} - var(--ide-btn-hover-border-width, #{$original-border}));
}
- .btn:not(.btn-link):not([disabled]):hover {
+ .btn:not(.gl-button):not(.btn-link):not([disabled]):hover {
border-width: var(--ide-btn-hover-border-width, 1px);
padding: calc-btn-hover-padding(6px) calc-btn-hover-padding(10px);
}
- .btn:not([disabled]).btn-sm:hover {
+ .btn:not(.gl-button):not([disabled]).btn-sm:hover {
padding: calc-btn-hover-padding(4px) calc-btn-hover-padding(10px);
}
- .btn:not([disabled]).btn-block:hover {
+ .btn:not(.gl-button):not([disabled]).btn-block:hover {
padding: calc-btn-hover-padding(6px) 0;
}
- .btn-default,
+ .btn-default:not(.gl-button),
.dropdown,
.dropdown-menu-toggle {
background-color: var(--ide-input-background, $white) !important;
@@ -258,7 +258,7 @@
}
// In IDE, the only inverted buttons are `.btn-remove`
- .btn-inverted.btn-remove {
+ .btn-inverted.btn-remove:not(.gl-button) {
color: var(--ide-input-color, $red-500) !important;
background-color: var(--ide-input-background, $white) !important;
border-color: var(--ide-btn-default-border, $red-500);
@@ -277,17 +277,21 @@
}
}
- .btn-default {
+ // todo: remove this block after all default buttons have been migrated to gl-button
+ .btn-default:not(.gl-button) {
+ background-color: var(--ide-btn-default-background, $white) !important;
+ border-color: var(--ide-btn-default-border, $border-color);
+
&:hover,
&:focus {
border-color: var(--ide-btn-default-hover-border, $border-white-normal) !important;
- background-color: var(--ide-input-background, $white-normal) !important;
+ background-color: var(--ide-btn-default-background, $white-normal) !important;
}
&:active,
.active {
border-color: var(--ide-btn-default-hover-border, $border-white-normal) !important;
- background-color: var(--ide-input-background, $white-dark) !important;
+ background-color: var(--ide-btn-default-background, $white-dark) !important;
}
}
@@ -321,8 +325,9 @@
border-color: var(--ide-dropdown-hover-background, $gray-100) !important;
}
- .btn-primary,
- .btn-info {
+ // todo: remove this block after all primary/info buttons have been migrated to gl-button
+ .btn-primary:not(.gl-button),
+ .btn-info:not(.gl-button) {
background-color: var(--ide-btn-primary-background, $blue-500);
border-color: var(--ide-btn-primary-border, $blue-600) !important;
@@ -339,7 +344,8 @@
}
}
- .btn-success {
+ // todo: remove this block after all success buttons have been migrated to gl-button
+ .btn-success:not(.gl-button) {
background-color: var(--ide-btn-success-background, $green-500);
border-color: var(--ide-btn-success-border, $green-600) !important;
@@ -356,12 +362,70 @@
}
}
- .btn[disabled] {
+ // todo: remove this block after all disabled buttons have been migrated to gl-button
+ .btn[disabled]:not(.gl-button) {
background-color: var(--ide-btn-default-background, $gray-light) !important;
border: 1px solid var(--ide-btn-disabled-border, $gray-100) !important;
color: var(--ide-btn-disabled-color, $gl-text-color-disabled) !important;
}
+ @function ide-btn-var($btn-type, $var-type, $value) {
+ @return var(--ide-btn-#{$btn-type}-#{$var-type}, $value);
+ }
+
+ @mixin ide-gl-button($btn-type, $bg-normal, $bg-hover, $bg-active, $border-normal, $border-hover, $border-focus, $border-active, $border-width-hover: 2px, $box-shadow-hover: $t-gray-a-08, $box-shadow-focus: 0 0 0 4px rgba($blue-500, 0.25)) {
+ background-color: ide-btn-var($btn-type, background, $bg-normal);
+ box-shadow: inset 0 0 0 1px ide-btn-var($btn-type, border, $border-normal);
+
+ &:hover,
+ &:focus {
+ background-color: ide-btn-var($btn-type, background, $bg-hover);
+ }
+
+ &:hover {
+ box-shadow: inset 0 0 0 ide-btn-var($btn-type, hover-border-width, $border-width-hover) ide-btn-var($btn-type, hover-border, $border-hover),
+ 0 2px 2px 0 $box-shadow-hover;
+ }
+
+ &:focus {
+ box-shadow: inset 0 0 0 ide-btn-var($btn-type, hover-border-width, $border-width-hover) ide-btn-var($btn-type, hover-border, $border-focus),
+ ide-btn-var($btn-type, focus-box-shadow, $box-shadow-focus);
+ }
+
+ &:active:focus {
+ background-color: ide-btn-var($btn-type, background, $bg-active);
+ box-shadow: inset 0 0 0 ide-btn-var($btn-type, hover-border-width, $border-width-hover) ide-btn-var($btn-type, hover-border, $border-active),
+ ide-btn-var($btn-type, focus-box-shadow, $box-shadow-focus);
+ }
+ }
+
+ .btn-default.gl-button.gl-button {
+ color: var(--ide-input-color, $gl-text-color);
+
+ @include ide-gl-button(default, $white, $gray-50, $gray-100, $gray-200, $gray-300, $gray-300, $gray-400);
+ }
+
+ .btn-success.gl-button.gl-button {
+ @include ide-gl-button(success, $green-500, $green-600, $green-800, $green-600, $green-800, $green-800, $green-900);
+ }
+
+ .btn-info.gl-button.gl-button,
+ .btn-primary.gl-button.gl-button {
+ @include ide-gl-button(primary, $blue-500, $blue-600, $blue-800, $blue-600, $blue-800, $blue-800, $blue-900);
+ }
+
+ .btn-danger.btn-danger-secondary.gl-button.gl-button {
+ color: var(--ide-input-color, $red-500);
+
+ @include ide-gl-button(danger-secondary, $white, $red-50, $red-100, $red-500, $red-600, $red-600, $red-700);
+ }
+
+ .btn[disabled].gl-button.gl-button {
+ color: var(--ide-btn-disabled-color, $gl-text-color-disabled);
+
+ @include ide-gl-button(disabled, $gray-10, $gray-10, $gray-10, $gray-100, $gray-100, $gray-100, $gray-100, 1px, transparent, transparent);
+ }
+
.md table:not(.code) tbody {
background-color: var(--ide-border-color, $white);
}
diff --git a/app/assets/stylesheets/page_bundles/ide_themes/_dark.scss b/app/assets/stylesheets/page_bundles/ide_themes/_dark.scss
index 37e6be9849b..41f9a8e6db7 100644
--- a/app/assets/stylesheets/page_bundles/ide_themes/_dark.scss
+++ b/app/assets/stylesheets/page_bundles/ide_themes/_dark.scss
@@ -20,20 +20,28 @@
--ide-btn-default-background: transparent;
--ide-btn-default-border: #bfbfbf;
--ide-btn-default-hover-border: #d8d8d8;
+ --ide-btn-default-hover-border-width: 2px;
+ --ide-btn-default-focus-box-shadow: 0 0 0 1px #bfbfbf;
--ide-btn-primary-background: #1068bf;
--ide-btn-primary-border: #428fdc;
--ide-btn-primary-hover-border: #63a6e9;
+ --ide-btn-primary-hover-border-width: 2px;
+ --ide-btn-primary-focus-box-shadow: 0 0 0 1px #63a6e9;
--ide-btn-success-background: #217645;
--ide-btn-success-border: #108548;
--ide-btn-success-hover-border: #2da160;
+ --ide-btn-success-hover-border-width: 2px;
+ --ide-btn-success-focus-box-shadow: 0 0 0 1px #2da160;
+ --ide-btn-disabled-background: transparent;
--ide-btn-disabled-border: rgba(223, 223, 223, 0.24);
+ --ide-btn-disabled-hover-border: rgba(223, 223, 223, 0.24);
+ --ide-btn-disabled-hover-border-width: 1px;
+ --ide-btn-disabled-focus-box-shadow: 0 0 0 0 transparent;
--ide-btn-disabled-color: rgba(145, 145, 145, 0.48);
- --ide-btn-hover-border-width: 2px;
-
--ide-dropdown-background: #404040;
--ide-dropdown-hover-background: #525252;
diff --git a/app/assets/stylesheets/page_bundles/ide_themes/_solarized-dark.scss b/app/assets/stylesheets/page_bundles/ide_themes/_solarized-dark.scss
index 0ef0834d8db..ccb6f7a333b 100644
--- a/app/assets/stylesheets/page_bundles/ide_themes/_solarized-dark.scss
+++ b/app/assets/stylesheets/page_bundles/ide_themes/_solarized-dark.scss
@@ -18,22 +18,30 @@
--ide-input-color: #fff;
--ide-btn-default-background: transparent;
- --ide-btn-default-border: var(--ide-input-border);
+ --ide-btn-default-border: #d8d8d8;
--ide-btn-default-hover-border: #d8d8d8;
+ --ide-btn-default-hover-border-width: 2px;
+ --ide-btn-default-focus-box-shadow: 0 0 0 1px #d8d8d8;
--ide-btn-primary-background: #1068bf;
--ide-btn-primary-border: #428fdc;
--ide-btn-primary-hover-border: #63a6e9;
+ --ide-btn-primary-hover-border-width: 2px;
+ --ide-btn-primary-focus-box-shadow: 0 0 0 1px #63a6e9;
--ide-btn-success-background: #217645;
--ide-btn-success-border: #108548;
--ide-btn-success-hover-border: #2da160;
+ --ide-btn-success-hover-border-width: 2px;
+ --ide-btn-success-focus-box-shadow: 0 0 0 1px #2da160;
+ --ide-btn-disabled-background: transparent;
--ide-btn-disabled-border: rgba(223, 223, 223, 0.24);
+ --ide-btn-disabled-hover-border: rgba(223, 223, 223, 0.24);
+ --ide-btn-disabled-hover-border-width: 1px;
+ --ide-btn-disabled-focus-box-shadow: transparent;
--ide-btn-disabled-color: rgba(145, 145, 145, 0.48);
- --ide-btn-hover-border-width: 2px;
-
--ide-dropdown-background: #004c61;
--ide-dropdown-hover-background: #00617a;
diff --git a/app/assets/stylesheets/page_bundles/jira_connect.scss b/app/assets/stylesheets/page_bundles/jira_connect.scss
index 83d16f29d49..b8cdd120e04 100644
--- a/app/assets/stylesheets/page_bundles/jira_connect.scss
+++ b/app/assets/stylesheets/page_bundles/jira_connect.scss
@@ -13,6 +13,7 @@ $atlaskit-border-color: #dfe1e6;
padding-top: $gl-padding-4;
.ak-button {
+ align-items: center;
height: auto;
margin-left: $btn-margin-5;
}
@@ -20,6 +21,74 @@ $atlaskit-border-color: #dfe1e6;
}
}
+$header-height: 40px;
+
+.jira-connect-header {
+ border-bottom: 1px solid $gray-100;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ min-height: $header-height;
+ padding-left: 16px;
+ padding-right: 16px;
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+}
+
+.jira-connect-user {
+ float: right;
+ position: relative;
+ top: -30px;
+}
+
+.jira-connect-app {
+ margin-top: $header-height;
+ max-width: 600px;
+ padding-top: 48px;
+ padding-left: 16px;
+ padding-right: 16px;
+ margin-left: auto;
+ margin-right: auto;
+ text-align: center;
+}
+
+.gl-mt-5 {
+ margin-top: 16px;
+}
+
+.heading-with-border {
+ border-bottom: 1px solid $gray-100;
+ display: inline-block;
+ padding-bottom: 16px;
+}
+
+svg {
+ fill: currentColor;
+
+ &.s16 {
+ height: 16px;
+ width: 16px;
+ }
+}
+
+.ak-field-group label {
+ text-align: left;
+}
+
+.ak-button__appearance-primary {
+ &:hover {
+ color: $white;
+ text-decoration: none;
+ }
+
+ svg {
+ align-self: center;
+ margin-left: 4px;
+ }
+}
+
.subscriptions {
tbody {
tr {
@@ -31,3 +100,11 @@ $atlaskit-border-color: #dfe1e6;
}
}
}
+
+.empty-subscriptions {
+ color: $gray-900;
+}
+
+.browser-limitations-notice {
+ margin-top: 32px;
+}
diff --git a/app/assets/stylesheets/page_bundles/jira_connect_users.scss b/app/assets/stylesheets/page_bundles/jira_connect_users.scss
new file mode 100644
index 00000000000..6725bf8f1a1
--- /dev/null
+++ b/app/assets/stylesheets/page_bundles/jira_connect_users.scss
@@ -0,0 +1,13 @@
+@import 'mixins_and_variables_and_functions';
+
+.jira-connect-users-container {
+ margin-left: auto;
+ margin-right: auto;
+ width: px-to-rem(350px);
+}
+
+.devise-layout-html body .navless-container {
+ @include media-breakpoint-down(xs) {
+ padding-top: 65px;
+ }
+}
diff --git a/app/controllers/jira_connect/events_controller.rb b/app/controllers/jira_connect/events_controller.rb
index 8f79c82d847..d833491b8f7 100644
--- a/app/controllers/jira_connect/events_controller.rb
+++ b/app/controllers/jira_connect/events_controller.rb
@@ -1,10 +1,14 @@
# frozen_string_literal: true
class JiraConnect::EventsController < JiraConnect::ApplicationController
+ # See https://developer.atlassian.com/cloud/jira/software/app-descriptor/#lifecycle
+
skip_before_action :verify_atlassian_jwt!, only: :installed
before_action :verify_qsh_claim!, only: :uninstalled
def installed
+ return head :ok if atlassian_jwt_valid?
+
installation = JiraConnectInstallation.new(install_params)
if installation.save
diff --git a/app/controllers/jira_connect/users_controller.rb b/app/controllers/jira_connect/users_controller.rb
new file mode 100644
index 00000000000..571d9f87779
--- /dev/null
+++ b/app/controllers/jira_connect/users_controller.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class JiraConnect::UsersController < ApplicationController
+ feature_category :integrations
+
+ layout 'devise_experimental_onboarding_issues'
+
+ def show
+ @jira_app_link = params.delete(:return_to)
+ end
+end
diff --git a/app/helpers/external_link_helper.rb b/app/helpers/external_link_helper.rb
index 9dbad1f5032..bf47087543f 100644
--- a/app/helpers/external_link_helper.rb
+++ b/app/helpers/external_link_helper.rb
@@ -3,7 +3,7 @@
module ExternalLinkHelper
def external_link(body, url, options = {})
link_to url, { target: '_blank', rel: 'noopener noreferrer' }.merge(options) do
- "#{body} #{icon('external-link')}".html_safe
+ "#{body} #{sprite_icon('external-link')}".html_safe
end
end
end
diff --git a/app/views/jira_connect/subscriptions/index.html.haml b/app/views/jira_connect/subscriptions/index.html.haml
index 349b3328c12..655c413f2a6 100644
--- a/app/views/jira_connect/subscriptions/index.html.haml
+++ b/app/views/jira_connect/subscriptions/index.html.haml
@@ -1,37 +1,61 @@
-%h1
- GitLab for Jira Configuration
-
-%form#add-subscription-form.subscription-form{ action: jira_connect_subscriptions_path }
- .ak-field-group
- %label
- Namespace
-
- .ak-field-group.field-group-input
- %input#namespace-input.ak-field-text{ type: 'text', required: true }
- %button.ak-button.ak-button__appearance-primary{ type: 'submit' }
- Link namespace to Jira
-
-%table.subscriptions
- %thead
- %tr
- %th Namespace
- %th Added
- %th
- %tbody
- - @subscriptions.each do |subscription|
- %tr
- %td= subscription.namespace.full_path
- %td= subscription.created_at
- %td= link_to 'Remove', jira_connect_subscription_path(subscription), class: 'remove-subscription'
-
-%p
- %strong Browser limitations:
- Adding a namespace currently works only in browsers that allow cross site cookies. Please make sure to use
- %a{ href: 'https://www.mozilla.org/en-US/firefox/', target: '_blank', rel: 'noopener noreferrer' } Firefox
- or
- %a{ href: 'https://www.google.com/chrome/index.html', target: '_blank', rel: 'noopener noreferrer' } Google Chrome
- or enable cross-site cookies in your browser when adding a namespace.
- %a{ href: 'https://gitlab.com/gitlab-org/gitlab/-/issues/263509', target: '_blank', rel: 'noopener noreferrer' } Learn more
+%header.jira-connect-header
+ = brand_header_logo
+
+.jira-connect-user
+ - if current_user
+ - user_link = link_to(current_user.to_reference, user_path(current_user), target: '_blank', rel: 'noopener noreferrer')
+ = _('Signed in to GitLab as %{user_link}').html_safe % { user_link: user_link }
+ - elsif @subscriptions.present?
+ = link_to _('Sign in to GitLab'), jira_connect_users_path, target: '_blank', rel: 'noopener noreferrer', class: 'js-jira-connect-sign-in'
+
+.jira-connect-app
+ %h1
+ GitLab for Jira Configuration
+
+ - if current_user.blank? && @subscriptions.empty?
+ %h2.heading-with-border Sign in to GitLab.com to get started.
+
+ .gl-mt-5
+ = external_link _('Sign in to GitLab'), jira_connect_users_path, class: 'ak-button ak-button__appearance-primary js-jira-connect-sign-in'
+
+ .gl-mt-5
+ %p Note: this integration only works with accounts on GitLab.com (SaaS).
+ - else
+ %form#add-subscription-form.subscription-form{ action: jira_connect_subscriptions_path }
+ .ak-field-group
+ %label
+ GitLab namespace
+
+ .ak-field-group.field-group-input
+ %input#namespace-input.ak-field-text{ type: 'text', required: true, placeholder: 'e.g. "MyCompany" or "MyCompany/GroupName"' }
+ %button.ak-button.ak-button__appearance-primary{ type: 'submit' }
+ Link namespace to Jira
+
+ - if @subscriptions.present?
+ %table.subscriptions
+ %thead
+ %tr
+ %th Namespace
+ %th Added
+ %th
+ %tbody
+ - @subscriptions.each do |subscription|
+ %tr
+ %td= subscription.namespace.full_path
+ %td= subscription.created_at
+ %td= link_to 'Remove', jira_connect_subscription_path(subscription), class: 'remove-subscription'
+ - else
+ %h4.empty-subscriptions
+ No linked namespaces
+
+ %p.browser-limitations-notice
+ %strong Browser limitations:
+ Adding a namespace currently works only in browsers that allow cross site cookies. Please make sure to use
+ %a{ href: 'https://www.mozilla.org/en-US/firefox/', target: '_blank', rel: 'noopener noreferrer' } Firefox
+ or
+ %a{ href: 'https://www.google.com/chrome/index.html', target: '_blank', rel: 'noopener noreferrer' } Google Chrome
+ or enable cross-site cookies in your browser when adding a namespace.
+ %a{ href: 'https://gitlab.com/gitlab-org/gitlab/-/issues/263509', target: '_blank', rel: 'noopener noreferrer' } Learn more
= page_specific_javascript_tag('jira_connect.js')
- add_page_specific_style 'page_bundles/jira_connect'
diff --git a/app/views/jira_connect/users/show.html.haml b/app/views/jira_connect/users/show.html.haml
new file mode 100644
index 00000000000..2ff92ab0dc8
--- /dev/null
+++ b/app/views/jira_connect/users/show.html.haml
@@ -0,0 +1,12 @@
+.jira-connect-users-container.gl-text-center
+ - user_link = link_to(current_user.to_reference, user_path(current_user), target: '_blank', rel: 'noopener noreferrer')
+ %h2= _('You are signed into GitLab as %{user_link}').html_safe % { user_link: user_link }
+
+ %p= s_('Integrations|You can now close this window and return to the GitLab for Jira application.')
+
+ - if @jira_app_link
+ %p= external_link s_('Integrations|Return to GitLab for Jira'), @jira_app_link, class: 'btn btn-success'
+
+ %p= link_to _('Sign out'), destroy_user_session_path, method: :post
+
+- add_page_specific_style 'page_bundles/jira_connect_users'
diff --git a/changelogs/unreleased/229114-jira-connect-install-webhook-for-updates.yml b/changelogs/unreleased/229114-jira-connect-install-webhook-for-updates.yml
new file mode 100644
index 00000000000..d86468981bc
--- /dev/null
+++ b/changelogs/unreleased/229114-jira-connect-install-webhook-for-updates.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Jira Connect App update webhooks
+merge_request: 45151
+author:
+type: fixed
diff --git a/changelogs/unreleased/235888-gitlab-for-jira-app-should-display-who-is-logged-in.yml b/changelogs/unreleased/235888-gitlab-for-jira-app-should-display-who-is-logged-in.yml
new file mode 100644
index 00000000000..bdcd4905d71
--- /dev/null
+++ b/changelogs/unreleased/235888-gitlab-for-jira-app-should-display-who-is-logged-in.yml
@@ -0,0 +1,5 @@
+---
+title: Add user sign in indicator to Jira connect app
+merge_request: 42628
+author:
+type: changed
diff --git a/config/application.rb b/config/application.rb
index bb961877f4c..7bb70c13580 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -182,6 +182,7 @@ module Gitlab
config.assets.precompile << "page_bundles/ide.css"
config.assets.precompile << "page_bundles/issues_list.css"
config.assets.precompile << "page_bundles/jira_connect.css"
+ config.assets.precompile << "page_bundles/jira_connect_users.css"
config.assets.precompile << "page_bundles/merge_conflicts.css"
config.assets.precompile << "page_bundles/merge_requests.css"
config.assets.precompile << "page_bundles/milestone.css"
diff --git a/config/feature_flags/development/global_default_branch_name.yml b/config/feature_flags/development/global_default_branch_name.yml
index 57b324a6da2..2954ed74062 100644
--- a/config/feature_flags/development/global_default_branch_name.yml
+++ b/config/feature_flags/development/global_default_branch_name.yml
@@ -1,7 +1,7 @@
---
name: global_default_branch_name
-introduced_by_url:
-rollout_issue_url:
-group:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35269
+rollout_issue_url:
+group: group::source code
type: development
default_enabled: true
diff --git a/config/feature_flags/development/mr_commit_neighbor_nav.yml b/config/feature_flags/development/mr_commit_neighbor_nav.yml
index 5fcacbdd3fe..7b540e14464 100644
--- a/config/feature_flags/development/mr_commit_neighbor_nav.yml
+++ b/config/feature_flags/development/mr_commit_neighbor_nav.yml
@@ -1,7 +1,7 @@
---
name: mr_commit_neighbor_nav
-introduced_by_url:
-rollout_issue_url:
-group:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28596
+rollout_issue_url:
+group: group::source code
type: development
default_enabled: true
diff --git a/config/routes/jira_connect.rb b/config/routes/jira_connect.rb
index a3b786b60f0..72b3f04f5e5 100644
--- a/config/routes/jira_connect.rb
+++ b/config/routes/jira_connect.rb
@@ -5,6 +5,7 @@ namespace :jira_connect do
root to: proc { [404, {}, ['']] }, as: 'base'
get 'app_descriptor' => 'app_descriptor#show'
+ get :users, to: 'users#show'
namespace :events do
post 'installed'
diff --git a/doc/development/api_graphql_styleguide.md b/doc/development/api_graphql_styleguide.md
index 184909e0099..3d4c033e676 100644
--- a/doc/development/api_graphql_styleguide.md
+++ b/doc/development/api_graphql_styleguide.md
@@ -385,8 +385,8 @@ end
GitLab's GraphQL API is versionless, which means we maintain backwards
compatibility with older versions of the API with every change. Rather
than removing a field or [enum value](#enums), we need to _deprecate_ it instead.
-In future, GitLab
-[may remove deprecated parts of the schema](https://gitlab.com/gitlab-org/gitlab/-/issues/32292).
+The deprecated parts of the schema can then be removed in a future release
+in accordance with [GitLab's deprecation process](../api/graphql/index.md#deprecation-process).
Fields and enum values are deprecated using the `deprecated` property.
The value of the property is a `Hash` of:
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 0be158add6f..36da7340c60 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -14149,6 +14149,9 @@ msgstr ""
msgid "Integrations|Projects using custom settings will not be impacted unless the project owner chooses to use instance-level defaults."
msgstr ""
+msgid "Integrations|Return to GitLab for Jira"
+msgstr ""
+
msgid "Integrations|Save settings?"
msgstr ""
@@ -14173,6 +14176,9 @@ msgstr ""
msgid "Integrations|When a Jira issue is mentioned in a commit or merge request a remote link and comment (if enabled) will be created."
msgstr ""
+msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
+msgstr ""
+
msgid "Interested parties can even contribute by pushing commits if they want to."
msgstr ""
@@ -24241,6 +24247,9 @@ msgstr ""
msgid "Sign in to \"%{group_name}\""
msgstr ""
+msgid "Sign in to GitLab"
+msgstr ""
+
msgid "Sign in using smart card"
msgstr ""
@@ -24286,6 +24295,9 @@ msgstr ""
msgid "Signed in"
msgstr ""
+msgid "Signed in to GitLab as %{user_link}"
+msgstr ""
+
msgid "Signed in with %{authentication} authentication"
msgstr ""
@@ -29859,6 +29871,9 @@ msgstr ""
msgid "You are receiving this message because you are a GitLab administrator for %{url}."
msgstr ""
+msgid "You are signed into GitLab as %{user_link}"
+msgstr ""
+
msgid "You are trying to upload something other than an image. Please upload a .png, .jpg, .jpeg, .gif, .bmp, .tiff or .ico."
msgstr ""
diff --git a/package.json b/package.json
index ffe38235d7e..1511c095d82 100644
--- a/package.json
+++ b/package.json
@@ -43,7 +43,7 @@
"@babel/preset-env": "^7.10.1",
"@gitlab/at.js": "1.5.5",
"@gitlab/svgs": "1.171.0",
- "@gitlab/ui": "21.30.1",
+ "@gitlab/ui": "21.32.1",
"@gitlab/visual-review-tools": "1.6.1",
"@rails/actioncable": "^6.0.3-3",
"@rails/ujs": "^6.0.3-2",
diff --git a/spec/controllers/jira_connect/events_controller_spec.rb b/spec/controllers/jira_connect/events_controller_spec.rb
index d1a2dd6e7af..8a07f69e480 100644
--- a/spec/controllers/jira_connect/events_controller_spec.rb
+++ b/spec/controllers/jira_connect/events_controller_spec.rb
@@ -4,14 +4,20 @@ require 'spec_helper'
RSpec.describe JiraConnect::EventsController do
describe '#installed' do
- subject do
- post :installed, params: {
- clientKey: '1234',
- sharedSecret: 'secret',
+ let(:client_key) { '1234' }
+ let(:shared_secret) { 'secret' }
+ let(:params) do
+ {
+ clientKey: client_key,
+ sharedSecret: shared_secret,
baseUrl: 'https://test.atlassian.net'
}
end
+ subject do
+ post :installed, params: params
+ end
+
it 'saves the jira installation data' do
expect { subject }.to change { JiraConnectInstallation.count }.by(1)
end
@@ -19,15 +25,15 @@ RSpec.describe JiraConnect::EventsController do
it 'saves the correct values' do
subject
- installation = JiraConnectInstallation.find_by_client_key('1234')
+ installation = JiraConnectInstallation.find_by_client_key(client_key)
- expect(installation.shared_secret).to eq('secret')
+ expect(installation.shared_secret).to eq(shared_secret)
expect(installation.base_url).to eq('https://test.atlassian.net')
end
context 'client key already exists' do
it 'returns 422' do
- create(:jira_connect_installation, client_key: '1234')
+ create(:jira_connect_installation, client_key: client_key)
subject
@@ -35,6 +41,23 @@ RSpec.describe JiraConnect::EventsController do
end
end
+ context 'when it is a version update and shared_secret is not sent' do
+ let(:params) do
+ {
+ clientKey: client_key,
+ baseUrl: 'https://test.atlassian.net'
+ }
+ end
+
+ it 'validates the JWT token in authorization header and returns 200 without creating a new installation' do
+ create(:jira_connect_installation, client_key: client_key, shared_secret: shared_secret)
+ request.headers["Authorization"] = "Bearer #{Atlassian::Jwt.encode({ iss: client_key }, shared_secret)}"
+
+ expect { subject }.not_to change { JiraConnectInstallation.count }
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+
describe '#uninstalled' do
let!(:installation) { create(:jira_connect_installation) }
let(:qsh) { Atlassian::Jwt.create_query_string_hash('https://gitlab.test/events/uninstalled', 'POST', 'https://gitlab.test') }
diff --git a/spec/frontend/static_site_editor/graphql/resolvers/has_submitted_changes_spec.js b/spec/frontend/static_site_editor/graphql/resolvers/has_submitted_changes_spec.js
new file mode 100644
index 00000000000..0670b240a3f
--- /dev/null
+++ b/spec/frontend/static_site_editor/graphql/resolvers/has_submitted_changes_spec.js
@@ -0,0 +1,27 @@
+import appDataQuery from '~/static_site_editor/graphql/queries/app_data.query.graphql';
+import hasSubmittedChanges from '~/static_site_editor/graphql/resolvers/has_submitted_changes';
+
+describe('static_site_editor/graphql/resolvers/has_submitted_changes', () => {
+ it('updates the cache with the data passed in input', () => {
+ const cachedData = { appData: { original: 'foo' } };
+ const newValue = { input: { hasSubmittedChanges: true } };
+
+ const cache = {
+ readQuery: jest.fn().mockReturnValue(cachedData),
+ writeQuery: jest.fn(),
+ };
+ hasSubmittedChanges(null, newValue, { cache });
+
+ expect(cache.readQuery).toHaveBeenCalledWith({ query: appDataQuery });
+ expect(cache.writeQuery).toHaveBeenCalledWith({
+ query: appDataQuery,
+ data: {
+ appData: {
+ __typename: 'AppData',
+ original: 'foo',
+ hasSubmittedChanges: true,
+ },
+ },
+ });
+ });
+});
diff --git a/spec/helpers/external_link_helper_spec.rb b/spec/helpers/external_link_helper_spec.rb
index b1a1884d887..f5bb0568824 100644
--- a/spec/helpers/external_link_helper_spec.rb
+++ b/spec/helpers/external_link_helper_spec.rb
@@ -6,12 +6,15 @@ RSpec.describe ExternalLinkHelper do
include IconsHelper
it 'returns external link with icon' do
- expect(external_link('https://gitlab.com', 'https://gitlab.com').to_s)
- .to eq('<a target="_blank" rel="noopener noreferrer" href="https://gitlab.com">https://gitlab.com <i aria-hidden="true" data-hidden="true" class="fa fa-external-link"></i></a>')
+ link = external_link('https://gitlab.com', 'https://gitlab.com').to_s
+ expect(link).to start_with('<a target="_blank" rel="noopener noreferrer" href="https://gitlab.com">https://gitlab.com')
+ expect(link).to include('data-testid="external-link-icon"')
end
it 'allows options when creating external link with icon' do
- expect(external_link('https://gitlab.com', 'https://gitlab.com', { "data-foo": "bar", class: "externalLink" }).to_s)
- .to eq('<a target="_blank" rel="noopener noreferrer" data-foo="bar" class="externalLink" href="https://gitlab.com">https://gitlab.com <i aria-hidden="true" data-hidden="true" class="fa fa-external-link"></i></a>')
+ link = external_link('https://gitlab.com', 'https://gitlab.com', { "data-foo": "bar", class: "externalLink" }).to_s
+
+ expect(link).to start_with('<a target="_blank" rel="noopener noreferrer" data-foo="bar" class="externalLink" href="https://gitlab.com">https://gitlab.com')
+ expect(link).to include('data-testid="external-link-icon"')
end
end
diff --git a/spec/views/jira_connect/subscriptions/index.html.haml_spec.rb b/spec/views/jira_connect/subscriptions/index.html.haml_spec.rb
new file mode 100644
index 00000000000..dcc36c93327
--- /dev/null
+++ b/spec/views/jira_connect/subscriptions/index.html.haml_spec.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'jira_connect/subscriptions/index.html.haml' do
+ let(:user) { build_stubbed(:user) }
+
+ before do
+ allow(view).to receive(:current_user).and_return(user)
+ assign(:subscriptions, [])
+ end
+
+ context 'when the user is signed in' do
+ it 'shows link to user profile' do
+ render
+
+ expect(rendered).to have_link(user.to_reference)
+ end
+ end
+
+ context 'when the user is not signed in' do
+ let(:user) { nil }
+
+ it 'shows "Sign in" link' do
+ render
+
+ expect(rendered).to have_link('Sign in to GitLab')
+ end
+ end
+end
diff --git a/yarn.lock b/yarn.lock
index ccdabf8e53b..8c4777f2797 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -866,10 +866,10 @@
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.171.0.tgz#abc3092bf804f0898301626130e0f3231834924a"
integrity sha512-TPfdqIxQDda+0CQHhb9XdF50lmqDmADu6yT8R4oZi6BoUtWLdiHbyFt+RnVU6t7EmjIKicNAii7Ga+f2ljCfUA==
-"@gitlab/ui@21.30.1":
- version "21.30.1"
- resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-21.30.1.tgz#561bd10c5264e48d16be4c5706827f40ec31286f"
- integrity sha512-JdLA8x7fOk1qgsqBeNhlmg1VTJIrl+ECWea8whoyqWnI95GPuiM5ZSnehZHA6FoNwB9n/u1GnVSLCHcqvHZW0w==
+"@gitlab/ui@21.32.1":
+ version "21.32.1"
+ resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-21.32.1.tgz#8ed29de1093afc36ea31d3cf93b047bcfe0c6543"
+ integrity sha512-ZZi/rJfDTXMytX1vNV2FU+l0fG6J7V2+1M7CWIkxdPIPVJ1LopkkfwnbBP29zrwBFBmguXcPoRfTjGa2oSNdbg==
dependencies:
"@babel/standalone" "^7.0.0"
"@gitlab/vue-toasted" "^1.3.0"