Commit adad2e8d authored by Mike Greiling's avatar Mike Greiling

Merge branch 'justin_ho-update-clean-up-jira-connect-app-code' into 'master'

Remove unused frontend code in Jira connect app

See merge request gitlab-org/gitlab!59470
parents 9d47864e 85fc8ab4
......@@ -3,7 +3,6 @@ import { GlAlert, GlButton, GlLink, GlModal, GlModalDirective, GlSprintf } from
import { mapState, mapMutations } from 'vuex';
import { retrieveAlert, getLocation } from '~/jira_connect/utils';
import { __ } from '~/locale';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { SET_ALERT } from '../store/mutation_types';
import GroupsList from './groups_list.vue';
import SubscriptionsList from './subscriptions_list.vue';
......@@ -22,7 +21,6 @@ export default {
directives: {
GlModalDirective,
},
mixins: [glFeatureFlagsMixin()],
inject: {
usersPath: {
default: '',
......
......@@ -23,13 +23,10 @@ export default {
</div>
<div>
<span
class="gl-mr-3 gl-text-gray-900! gl-font-weight-bold"
data-testid="group-list-item-name"
>
<span class="gl-mr-3 gl-text-gray-900! gl-font-weight-bold">
{{ group.full_name }}
</span>
<div v-if="group.description" data-testid="group-list-item-description">
<div v-if="group.description">
<p class="gl-mt-2! gl-mb-0 gl-text-gray-600" v-text="group.description"></p>
</div>
</div>
......
<script>
import { GlButton, GlEmptyState, GlTable } from '@gitlab/ui';
import { isEmpty } from 'lodash';
import { mapMutations } from 'vuex';
import { removeSubscription } from '~/jira_connect/api';
import { reloadPage } from '~/jira_connect/utils';
import { __, s__ } from '~/locale';
import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import { SET_ALERT } from '../store/mutation_types';
import GroupItemName from './group_item_name.vue';
export default {
......@@ -46,8 +48,12 @@ export default {
emptyDescription: s__(
'Integrations|Namespaces are the GitLab groups and subgroups you link to this Jira instance.',
),
unlinkError: s__('Integrations|Failed to unlink namespace. Please try again.'),
},
methods: {
...mapMutations({
setAlert: SET_ALERT,
}),
isEmpty,
isLoadingItem(item) {
return this.loadingItem === item;
......@@ -62,7 +68,11 @@ export default {
.then(() => {
reloadPage();
})
.catch(() => {
.catch((error) => {
this.setAlert({
message: error?.response?.data?.error || this.$options.i18n.unlinkError,
variant: 'danger',
});
this.loadingItem = null;
});
},
......@@ -89,6 +99,7 @@ export default {
:class="unlinkBtnClass(item)"
category="secondary"
:loading="isLoadingItem(item)"
:disabled="!isEmpty(loadingItem)"
@click.prevent="onClick(item)"
>{{ __('Unlink') }}</gl-button
>
......
import setConfigs from '@gitlab/ui/dist/config';
import Vue from 'vue';
import { addSubscription, removeSubscription } from '~/jira_connect/api';
import { getLocation, reloadPage, sizeToParent } from '~/jira_connect/utils';
import { getLocation, sizeToParent } from '~/jira_connect/utils';
import GlFeatureFlagsPlugin from '~/vue_shared/gl_feature_flags_plugin';
import Translate from '~/vue_shared/translate';
import JiraConnectApp from './components/app.vue';
import createStore from './store';
import { SET_ALERT } from './store/mutation_types';
const store = createStore();
const reqFailed = (res, fallbackErrorMessage) => {
const { error = fallbackErrorMessage } = res || {};
store.commit(SET_ALERT, { message: error, variant: 'danger' });
};
const updateSignInLinks = async () => {
const location = await getLocation();
Array.from(document.querySelectorAll('.js-jira-connect-sign-in')).forEach((el) => {
......@@ -25,43 +17,7 @@ const updateSignInLinks = async () => {
});
};
const initRemoveSubscriptionButtonHandlers = () => {
Array.from(document.querySelectorAll('.js-jira-connect-remove-subscription')).forEach((el) => {
el.addEventListener('click', function onRemoveSubscriptionClick(e) {
e.preventDefault();
const removePath = e.target.getAttribute('href');
removeSubscription(removePath)
.then(reloadPage)
.catch((err) =>
reqFailed(err.response.data, 'Failed to remove namespace. Please try again.'),
);
});
});
};
const initAddSubscriptionFormHandler = () => {
const formEl = document.querySelector('#add-subscription-form');
if (!formEl) {
return;
}
formEl.addEventListener('submit', function onAddSubscriptionForm(e) {
e.preventDefault();
const addPath = e.target.getAttribute('action');
const namespace = (e.target.querySelector('#namespace-input') || {}).value;
addSubscription(addPath, namespace)
.then(reloadPage)
.catch((err) => reqFailed(err.response.data, 'Failed to add namespace. Please try again.'));
});
};
export async function initJiraConnect() {
initAddSubscriptionFormHandler();
initRemoveSubscriptionButtonHandlers();
await updateSignInLinks();
const el = document.querySelector('.js-jira-connect-app');
......
......@@ -8,7 +8,6 @@
// We should only import styles that we actually use.
@import '@gitlab/ui/src/components/base/alert/alert';
@import '@gitlab/ui/src/components/base/avatar/avatar';
@import '@gitlab/ui/src/components/base/badge/badge';
@import '@gitlab/ui/src/components/base/button/button';
@import '@gitlab/ui/src/components/base/icon/icon';
@import '@gitlab/ui/src/components/base/link/link';
......@@ -19,22 +18,8 @@
@import '@gitlab/ui/src/components/base/tooltip/tooltip';
@import '@gitlab/ui/src/components/base/search_box_by_type/search_box_by_type';
$atlaskit-border-color: #dfe1e6;
$header-height: 40px;
.subscription-form {
.field-group-input {
display: flex;
padding-top: $gl-padding-4;
.ak-button {
align-items: center;
height: auto;
margin-left: $btn-margin-5;
}
}
}
.jira-connect-header {
min-height: $header-height;
position: fixed;
......@@ -60,41 +45,3 @@ $header-height: 40px;
margin-left: auto;
margin-right: auto;
}
// for external_link buttons
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 {
border-bottom: 1px solid $atlaskit-border-color;
}
td {
padding: $gl-padding-8;
}
}
}
......@@ -17173,6 +17173,9 @@ msgstr ""
msgid "Integrations|Failed to load namespaces. Please try again."
msgstr ""
msgid "Integrations|Failed to unlink namespace. Please try again."
msgstr ""
msgid "Integrations|Includes Standard plus entire commit message, commit hash, and issue IDs"
msgstr ""
......
......@@ -26,16 +26,13 @@ exports[`GroupItemName template matches the snapshot 1`] = `
<div>
<span
class="gl-mr-3 gl-text-gray-900! gl-font-weight-bold"
data-testid="group-list-item-name"
>
Gitlab Org
</span>
<div
data-testid="group-list-item-description"
>
<div>
<p
class="gl-mt-2! gl-mb-0 gl-text-gray-600"
>
......
import { GlButton, GlEmptyState, GlTable } from '@gitlab/ui';
import { mount, shallowMount } from '@vue/test-utils';
import waitForPromises from 'helpers/wait_for_promises';
import * as JiraConnectApi from '~/jira_connect/api';
import SubscriptionsList from '~/jira_connect/components/subscriptions_list.vue';
import createStore from '~/jira_connect/store';
import { SET_ALERT } from '~/jira_connect/store/mutation_types';
import { reloadPage } from '~/jira_connect/utils';
import { mockSubscription } from '../mock_data';
jest.mock('~/jira_connect/utils');
describe('SubscriptionsList', () => {
let wrapper;
let store;
const createComponent = ({ mountFn = shallowMount, provide = {} } = {}) => {
store = createStore();
wrapper = mountFn(SubscriptionsList, {
provide,
store,
});
};
afterEach(() => {
wrapper.destroy();
});
const findGlEmptyState = () => wrapper.findComponent(GlEmptyState);
const findGlTable = () => wrapper.findComponent(GlTable);
const findUnlinkButton = () => findGlTable().findComponent(GlButton);
const clickUnlinkButton = () => findUnlinkButton().trigger('click');
describe('template', () => {
it('renders GlEmptyState when subscriptions is empty', () => {
createComponent();
expect(findGlEmptyState().exists()).toBe(true);
expect(findGlTable().exists()).toBe(false);
});
it('renders GlTable when subscriptions are present', () => {
createComponent({
provide: {
subscriptions: [mockSubscription],
},
});
expect(findGlEmptyState().exists()).toBe(false);
expect(findGlTable().exists()).toBe(true);
});
});
describe('on "Unlink" button click', () => {
let removeSubscriptionSpy;
beforeEach(() => {
createComponent({
mountFn: mount,
provide: {
subscriptions: [mockSubscription],
},
});
removeSubscriptionSpy = jest.spyOn(JiraConnectApi, 'removeSubscription').mockResolvedValue();
});
it('sets button to loading and sends request', async () => {
expect(findUnlinkButton().props('loading')).toBe(false);
clickUnlinkButton();
await wrapper.vm.$nextTick();
expect(findUnlinkButton().props('loading')).toBe(true);
await waitForPromises();
expect(removeSubscriptionSpy).toHaveBeenCalledWith(mockSubscription.unlink_path);
});
describe('when request is successful', () => {
it('reloads the page', async () => {
clickUnlinkButton();
await waitForPromises();
expect(reloadPage).toHaveBeenCalled();
});
});
describe('when request has errors', () => {
const mockErrorMessage = 'error message';
const mockError = { response: { data: { error: mockErrorMessage } } };
beforeEach(() => {
jest.spyOn(JiraConnectApi, 'removeSubscription').mockRejectedValue(mockError);
jest.spyOn(store, 'commit');
});
it('sets alert', async () => {
clickUnlinkButton();
await waitForPromises();
expect(reloadPage).not.toHaveBeenCalled();
expect(store.commit.mock.calls).toEqual(
expect.arrayContaining([
[
SET_ALERT,
{
message: mockErrorMessage,
variant: 'danger',
},
],
]),
);
});
});
});
});
import waitForPromises from 'helpers/wait_for_promises';
import { initJiraConnect } from '~/jira_connect';
import { removeSubscription } from '~/jira_connect/api';
jest.mock('~/jira_connect/api', () => ({
removeSubscription: jest.fn().mockResolvedValue(),
}));
jest.mock('~/jira_connect/utils', () => ({
getLocation: jest.fn().mockResolvedValue('test/location'),
......@@ -15,10 +9,6 @@ describe('initJiraConnect', () => {
setFixtures(`
<a class="js-jira-connect-sign-in" href="https://gitlab.com">Sign In</a>
<a class="js-jira-connect-sign-in" href="https://gitlab.com">Another Sign In</a>
<a href="https://gitlab.com/sub1" class="js-jira-connect-remove-subscription">Remove</a>
<a href="https://gitlab.com/sub2" class="js-jira-connect-remove-subscription">Remove</a>
<a href="https://gitlab.com/sub3" class="js-jira-connect-remove-subscription">Remove</a>
`);
await initJiraConnect();
......@@ -31,23 +21,4 @@ describe('initJiraConnect', () => {
});
});
});
describe('`remove subscription` buttons', () => {
describe('on click', () => {
it('calls `removeSubscription`', () => {
Array.from(document.querySelectorAll('.js-jira-connect-remove-subscription')).forEach(
(removeSubscriptionButton) => {
removeSubscriptionButton.dispatchEvent(new Event('click'));
waitForPromises();
expect(removeSubscription).toHaveBeenCalledWith(removeSubscriptionButton.href);
expect(removeSubscription).toHaveBeenCalledTimes(1);
removeSubscription.mockClear();
},
);
});
});
});
});
......@@ -15,3 +15,9 @@ export const mockGroup2 = {
full_path: 'gitlab-com',
description: 'For GitLab company related projects',
};
export const mockSubscription = {
group: mockGroup1,
created_at: '2021-04-14T08:52:23.115Z',
unlink_path: '/-/jira_connect/subscriptions/1',
};
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment