Commit 3d2e8da5 authored by Kushal Pandya's avatar Kushal Pandya

Merge branch 'cngo-sort-issues-init' into 'master'

Tidy ~/issues init functions

See merge request gitlab-org/gitlab!77032
parents 4b2a9b08 e46c5402
/* eslint-disable no-new */
import $ from 'jquery';
import IssuableForm from 'ee_else_ce/issuable/issuable_form';
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
import GLForm from '~/gl_form';
import { initTitleSuggestions, initTypePopover } from '~/issues/new';
import LabelsSelect from '~/labels/labels_select';
import MilestoneSelect from '~/milestones/milestone_select';
import IssuableTemplateSelectors from '~/issuable/issuable_template_selectors';
export default () => {
new ShortcutsNavigation();
new GLForm($('.issue-form'));
new IssuableForm($('.issue-form'));
new LabelsSelect();
new MilestoneSelect();
new IssuableTemplateSelectors({
warnTemplateOverride: true,
});
initTitleSuggestions();
initTypePopover();
};
import $ from 'jquery';
import IssuableForm from 'ee_else_ce/issuable/issuable_form';
import loadAwardsHandler from '~/awards_handler';
import ShortcutsIssuable from '~/behaviors/shortcuts/shortcuts_issuable';
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
import GLForm from '~/gl_form';
import { initIssuableHeaderWarnings, initIssuableSidebar } from '~/issuable';
import IssuableTemplateSelectors from '~/issuable/issuable_template_selectors';
import Issue from '~/issues/issue';
import { initTitleSuggestions, initTypePopover } from '~/issues/new';
import { initRelatedMergeRequests } from '~/issues/related_merge_requests';
import {
initHeaderActions,
initIncidentApp,
initIssueApp,
initSentryErrorStackTrace,
} from '~/issues/show';
import { parseIssuableData } from '~/issues/show/utils/parse_data';
import LabelsSelect from '~/labels/labels_select';
import MilestoneSelect from '~/milestones/milestone_select';
import initNotesApp from '~/notes';
import { store } from '~/notes/stores';
import { IssuableType } from '~/vue_shared/issuable/show/constants';
import ZenMode from '~/zen_mode';
import FilteredSearchServiceDesk from './filtered_search_service_desk';
export function initFilteredSearchServiceDesk() {
if (document.querySelector('.filtered-search')) {
const supportBotData = JSON.parse(
document.querySelector('.js-service-desk-issues').dataset.supportBot,
);
const filteredSearchManager = new FilteredSearchServiceDesk(supportBotData);
filteredSearchManager.setup();
}
}
export function initForm() {
new GLForm($('.issue-form')); // eslint-disable-line no-new
new IssuableForm($('.issue-form')); // eslint-disable-line no-new
new IssuableTemplateSelectors({ warnTemplateOverride: true }); // eslint-disable-line no-new
new LabelsSelect(); // eslint-disable-line no-new
new MilestoneSelect(); // eslint-disable-line no-new
new ShortcutsNavigation(); // eslint-disable-line no-new
initTitleSuggestions();
initTypePopover();
}
export function initShow() {
const el = document.getElementById('js-issuable-app');
if (!el) {
return;
}
const { issueType, ...issuableData } = parseIssuableData(el);
if (issueType === IssuableType.Incident) {
initIncidentApp(issuableData);
initHeaderActions(store, IssuableType.Incident);
} else {
initIssueApp(issuableData, store);
initHeaderActions(store);
}
new Issue(); // eslint-disable-line no-new
new ShortcutsIssuable(); // eslint-disable-line no-new
new ZenMode(); // eslint-disable-line no-new
initIssuableHeaderWarnings(store);
initIssuableSidebar();
initNotesApp();
initRelatedMergeRequests();
initSentryErrorStackTrace();
const awardEmojiEl = document.getElementById('js-vue-awards-block');
if (awardEmojiEl) {
import('~/emoji/awards_app')
.then((m) => m.default(awardEmojiEl))
.catch(() => {});
} else {
loadAwardsHandler();
}
import(/* webpackChunkName: 'design_management' */ '~/design_management')
.then((module) => module.default())
.catch(() => {});
}
import FilteredSearchServiceDesk from './filtered_search_service_desk';
export function initFilteredSearchServiceDesk() {
if (document.querySelector('.filtered-search')) {
const supportBotData = JSON.parse(
document.querySelector('.js-service-desk-issues').dataset.supportBot,
);
const filteredSearchManager = new FilteredSearchServiceDesk(supportBotData);
filteredSearchManager.setup();
}
}
......@@ -5,8 +5,6 @@ import TitleSuggestions from './components/title_suggestions.vue';
import TypePopover from './components/type_popover.vue';
export function initTitleSuggestions() {
Vue.use(VueApollo);
const el = document.getElementById('js-suggestions');
const issueTitle = document.getElementById('issue_title');
......@@ -14,6 +12,8 @@ export function initTitleSuggestions() {
return undefined;
}
Vue.use(VueApollo);
const apolloProvider = new VueApollo({
defaultClient: createDefaultClient(),
});
......
......@@ -2,23 +2,21 @@ import Vue from 'vue';
import RelatedMergeRequests from './components/related_merge_requests.vue';
import createStore from './store';
export default function initRelatedMergeRequests() {
const relatedMergeRequestsElement = document.querySelector('#js-related-merge-requests');
export function initRelatedMergeRequests() {
const el = document.querySelector('#js-related-merge-requests');
if (relatedMergeRequestsElement) {
const { endpoint, projectPath, projectNamespace } = relatedMergeRequestsElement.dataset;
if (!el) {
return undefined;
}
const { endpoint, projectPath, projectNamespace } = el.dataset;
// eslint-disable-next-line no-new
new Vue({
el: relatedMergeRequestsElement,
components: {
RelatedMergeRequests,
},
return new Vue({
el,
store: createStore(),
render: (createElement) =>
createElement('related-merge-requests', {
createElement(RelatedMergeRequests, {
props: { endpoint, projectNamespace, projectPath },
}),
});
}
}
import Vue from 'vue';
import store from '~/error_tracking/store';
import SentryErrorStackTrace from './components/sentry_error_stack_trace.vue';
export default function initSentryErrorStacktrace() {
const sentryErrorStackTraceEl = document.querySelector('#js-sentry-error-stack-trace');
if (sentryErrorStackTraceEl) {
const { issueStackTracePath } = sentryErrorStackTraceEl.dataset;
// eslint-disable-next-line no-new
new Vue({
el: sentryErrorStackTraceEl,
components: {
SentryErrorStackTrace,
},
store,
render: (createElement) =>
createElement('sentry-error-stack-trace', {
props: { issueStackTracePath },
}),
});
}
}
import loadAwardsHandler from '~/awards_handler';
import ShortcutsIssuable from '~/behaviors/shortcuts/shortcuts_issuable';
import { initIssuableHeaderWarnings, initIssuableSidebar } from '~/issuable';
import { IssuableType } from '~/vue_shared/issuable/show/constants';
import Issue from '~/issues/issue';
import { initIncidentApp, initIncidentHeaderActions } from '~/issues/show/incident';
import { initIssuableApp, initIssueHeaderActions } from '~/issues/show/issue';
import { parseIssuableData } from '~/issues/show/utils/parse_data';
import initNotesApp from '~/notes';
import { store } from '~/notes/stores';
import initRelatedMergeRequestsApp from '~/issues/related_merge_requests';
import initSentryErrorStackTraceApp from '~/issues/sentry_error_stack_trace';
import ZenMode from '~/zen_mode';
export default function initShowIssue() {
initNotesApp();
const initialDataEl = document.getElementById('js-issuable-app');
const { issueType, ...issuableData } = parseIssuableData(initialDataEl);
switch (issueType) {
case IssuableType.Incident:
initIncidentApp(issuableData);
initIncidentHeaderActions(store);
break;
case IssuableType.Issue:
initIssuableApp(issuableData, store);
initIssueHeaderActions(store);
break;
default:
initIssueHeaderActions(store);
break;
}
initIssuableHeaderWarnings(store);
initSentryErrorStackTraceApp();
initRelatedMergeRequestsApp();
import(/* webpackChunkName: 'design_management' */ '~/design_management')
.then((module) => module.default())
.catch(() => {});
new ZenMode(); // eslint-disable-line no-new
if (issueType !== IssuableType.TestCase) {
const awardEmojiEl = document.getElementById('js-vue-awards-block');
new Issue(); // eslint-disable-line no-new
new ShortcutsIssuable(); // eslint-disable-line no-new
initIssuableSidebar();
if (awardEmojiEl) {
import('~/emoji/awards_app')
.then((m) => m.default(awardEmojiEl))
.catch(() => {});
} else {
loadAwardsHandler();
}
}
}
import Vue from 'vue';
import { mapGetters } from 'vuex';
import errorTrackingStore from '~/error_tracking/store';
import { parseBoolean } from '~/lib/utils/common_utils';
import issuableApp from './components/app.vue';
import incidentTabs from './components/incidents/incident_tabs.vue';
import { issueState, IncidentType } from './constants';
import IssueApp from './components/app.vue';
import HeaderActions from './components/header_actions.vue';
import IncidentTabs from './components/incidents/incident_tabs.vue';
import SentryErrorStackTrace from './components/sentry_error_stack_trace.vue';
import { IncidentType, issueState } from './constants';
import apolloProvider from './graphql';
import getIssueStateQuery from './queries/get_issue_state.query.graphql';
import HeaderActions from './components/header_actions.vue';
const bootstrapApollo = (state = {}) => {
return apolloProvider.clients.defaultClient.cache.writeQuery({
......@@ -16,7 +19,7 @@ const bootstrapApollo = (state = {}) => {
});
};
export function initIncidentApp(issuableData = {}) {
export function initIncidentApp(issueData = {}) {
const el = document.getElementById('js-issuable-app');
if (!el) {
......@@ -34,16 +37,13 @@ export function initIncidentApp(issuableData = {}) {
projectId,
slaFeatureAvailable,
uploadMetricsFeatureAvailable,
} = issuableData;
} = issueData;
const fullPath = `${projectNamespace}/${projectPath}`;
return new Vue({
el,
apolloProvider,
components: {
issuableApp,
},
provide: {
issueType: IncidentType,
canCreateIncident,
......@@ -55,10 +55,10 @@ export function initIncidentApp(issuableData = {}) {
uploadMetricsFeatureAvailable: parseBoolean(uploadMetricsFeatureAvailable),
},
render(createElement) {
return createElement('issuable-app', {
return createElement(IssueApp, {
props: {
...issuableData,
descriptionComponent: incidentTabs,
...issueData,
descriptionComponent: IncidentTabs,
showTitleBorder: false,
},
});
......@@ -66,7 +66,42 @@ export function initIncidentApp(issuableData = {}) {
});
}
export function initIncidentHeaderActions(store) {
export function initIssueApp(issueData, store) {
const el = document.getElementById('js-issuable-app');
if (!el) {
return undefined;
}
bootstrapApollo({ ...issueState, issueType: el.dataset.issueType });
const { canCreateIncident, ...issueProps } = issueData;
return new Vue({
el,
apolloProvider,
store,
provide: {
canCreateIncident,
},
computed: {
...mapGetters(['getNoteableData']),
},
render(createElement) {
return createElement(IssueApp, {
props: {
...issueProps,
isConfidential: this.getNoteableData?.confidential,
isLocked: this.getNoteableData?.discussion_locked,
issuableStatus: this.getNoteableData?.state,
id: this.getNoteableData?.id,
},
});
},
});
}
export function initHeaderActions(store, type = '') {
const el = document.querySelector('.js-issue-header-actions');
if (!el) {
......@@ -75,12 +110,15 @@ export function initIncidentHeaderActions(store) {
bootstrapApollo({ ...issueState, issueType: el.dataset.issueType });
const canCreate =
type === IncidentType ? el.dataset.canCreateIncident : el.dataset.canCreateIssue;
return new Vue({
el,
apolloProvider,
store,
provide: {
canCreateIssue: parseBoolean(el.dataset.canCreateIncident),
canCreateIssue: parseBoolean(canCreate),
canDestroyIssue: parseBoolean(el.dataset.canDestroyIssue),
canPromoteToEpic: parseBoolean(el.dataset.canPromoteToEpic),
canReopenIssue: parseBoolean(el.dataset.canReopenIssue),
......@@ -99,3 +137,20 @@ export function initIncidentHeaderActions(store) {
render: (createElement) => createElement(HeaderActions),
});
}
export function initSentryErrorStackTrace() {
const el = document.querySelector('#js-sentry-error-stack-trace');
if (!el) {
return undefined;
}
const { issueStackTracePath } = el.dataset;
return new Vue({
el,
store: errorTrackingStore,
render: (createElement) =>
createElement(SentryErrorStackTrace, { props: { issueStackTracePath } }),
});
}
import Vue from 'vue';
import { mapGetters } from 'vuex';
import { parseBoolean } from '~/lib/utils/common_utils';
import IssuableApp from './components/app.vue';
import HeaderActions from './components/header_actions.vue';
import { issueState } from './constants';
import apolloProvider from './graphql';
import getIssueStateQuery from './queries/get_issue_state.query.graphql';
const bootstrapApollo = (state = {}) => {
return apolloProvider.clients.defaultClient.cache.writeQuery({
query: getIssueStateQuery,
data: {
issueState: state,
},
});
};
export function initIssuableApp(issuableData, store) {
const el = document.getElementById('js-issuable-app');
if (!el) {
return undefined;
}
bootstrapApollo({ ...issueState, issueType: el.dataset.issueType });
const { canCreateIncident, ...issuableProps } = issuableData;
return new Vue({
el,
apolloProvider,
store,
provide: {
canCreateIncident,
},
computed: {
...mapGetters(['getNoteableData']),
},
render(createElement) {
return createElement(IssuableApp, {
props: {
...issuableProps,
isConfidential: this.getNoteableData?.confidential,
isLocked: this.getNoteableData?.discussion_locked,
issuableStatus: this.getNoteableData?.state,
id: this.getNoteableData?.id,
},
});
},
});
}
export function initIssueHeaderActions(store) {
const el = document.querySelector('.js-issue-header-actions');
if (!el) {
return undefined;
}
bootstrapApollo({ ...issueState, issueType: el.dataset.issueType });
return new Vue({
el,
apolloProvider,
store,
provide: {
canCreateIssue: parseBoolean(el.dataset.canCreateIssue),
canDestroyIssue: parseBoolean(el.dataset.canDestroyIssue),
canPromoteToEpic: parseBoolean(el.dataset.canPromoteToEpic),
canReopenIssue: parseBoolean(el.dataset.canReopenIssue),
canReportSpam: parseBoolean(el.dataset.canReportSpam),
canUpdateIssue: parseBoolean(el.dataset.canUpdateIssue),
iid: el.dataset.iid,
isIssueAuthor: parseBoolean(el.dataset.isIssueAuthor),
issuePath: el.dataset.issuePath,
issueType: el.dataset.issueType,
newIssuePath: el.dataset.newIssuePath,
projectPath: el.dataset.projectPath,
projectId: el.dataset.projectId,
reportAbusePath: el.dataset.reportAbusePath,
submitAsSpamPath: el.dataset.submitAsSpamPath,
},
render: (createElement) => createElement(HeaderActions),
});
}
import { initShow } from '~/issues';
import initRelatedIssues from '~/related_issues';
import initSidebarBundle from '~/sidebar/sidebar_bundle';
import initShow from '~/issues/show';
initShow();
initSidebarBundle();
......
import initForm from 'ee_else_ce/issues/form';
import { initForm } from 'ee_else_ce/issues';
initForm();
import initForm from 'ee_else_ce/issues/form';
import { initForm } from 'ee_else_ce/issues';
initForm();
import { initFilteredSearchServiceDesk } from '~/issues';
import { mountIssuablesListApp } from '~/issues_list';
import { initFilteredSearchServiceDesk } from '~/issues/init_filtered_search_service_desk';
initFilteredSearchServiceDesk();
......
import { initShow } from '~/issues';
import { store } from '~/notes/stores';
import initRelatedIssues from '~/related_issues';
import initSidebarBundle from '~/sidebar/sidebar_bundle';
import initShow from '~/issues/show';
initShow();
initSidebarBundle(store);
......
import initEpicsSelect from 'ee/vue_shared/components/sidebar/epics_select/epics_select_bundle';
import initForm from '~/issues/form';
export default () => {
initEpicsSelect();
initForm();
};
import Vue from 'vue';
import initEpicsSelect from 'ee/vue_shared/components/sidebar/epics_select/epics_select_bundle';
import { initForm as initFormCE } from '~/issues';
import RelatedFeatureFlags from './components/related_feature_flags.vue';
import UnableToLinkVulnerabilityError from './components/unable_to_link_vulnerability_error.vue';
export function initForm() {
initEpicsSelect();
initFormCE();
}
export function initRelatedFeatureFlags() {
const el = document.querySelector('#js-related-feature-flags-root');
if (el) {
/* eslint-disable-next-line no-new */
new Vue({
if (!el) {
return undefined;
}
return new Vue({
el,
provide: { endpoint: el.dataset.endpoint },
render(h) {
return h(RelatedFeatureFlags);
},
render: (createElement) => createElement(RelatedFeatureFlags),
});
}
export function initUnableToLinkVulnerabilityError() {
const el = document.querySelector('#js-unable-to-link-vulnerability');
if (!el) {
return undefined;
}
const { vulnerabilityLink } = el.dataset;
return new Vue({
el,
render: (createElement) =>
createElement(UnableToLinkVulnerabilityError, { props: { vulnerabilityLink } }),
});
}
import Vue from 'vue';
import App from './components/unable_to_link_vulnerability_error.vue';
export default () => {
const el = document.querySelector('#js-unable-to-link-vulnerability');
if (!el) return null;
const { vulnerabilityLink } = el.dataset;
return new Vue({
el,
render: (h) =>
h(App, {
props: { vulnerabilityLink },
}),
});
};
import { initRelatedFeatureFlags } from 'ee/issues';
import { initRelatedFeatureFlags, initUnableToLinkVulnerabilityError } from 'ee/issues';
import { initShow } from '~/issues';
import { store } from '~/notes/stores';
import initShow from '~/issues/show';
import initRelatedIssues from '~/related_issues';
import initSidebarBundle from '~/sidebar/sidebar_bundle';
import initUnableToLinkVulnerabilityError from 'ee/issues/init_unable_to_link_vulnerability_error';
import UserCallout from '~/user_callout';
initShow();
......@@ -12,7 +11,5 @@ initRelatedIssues();
initRelatedFeatureFlags();
initUnableToLinkVulnerabilityError();
// eslint-disable-next-line no-new
new UserCallout({ className: 'js-epics-sidebar-callout' });
// eslint-disable-next-line no-new
new UserCallout({ className: 'js-weight-sidebar-callout' });
new UserCallout({ className: 'js-epics-sidebar-callout' }); // eslint-disable-line no-new
new UserCallout({ className: 'js-weight-sidebar-callout' }); // eslint-disable-line no-new
import Vue from 'vue';
import { GlLoadingIcon } from '@gitlab/ui';
import { createLocalVue, shallowMount } from '@vue/test-utils';
import { shallowMount } from '@vue/test-utils';
import Vuex from 'vuex';
import Stacktrace from '~/error_tracking/components/stacktrace.vue';
import SentryErrorStackTrace from '~/issues/sentry_error_stack_trace/components/sentry_error_stack_trace.vue';
const localVue = createLocalVue();
localVue.use(Vuex);
import SentryErrorStackTrace from '~/issues/show/components/sentry_error_stack_trace.vue';
describe('Sentry Error Stack Trace', () => {
let actions;
......@@ -13,13 +11,14 @@ describe('Sentry Error Stack Trace', () => {
let store;
let wrapper;
Vue.use(Vuex);
function mountComponent({
stubs = {
stacktrace: Stacktrace,
},
} = {}) {
wrapper = shallowMount(SentryErrorStackTrace, {
localVue,
stubs,
store,
propsData: {
......
import MockAdapter from 'axios-mock-adapter';
import waitForPromises from 'helpers/wait_for_promises';
import { initIssuableApp } from '~/issues/show/issue';
import { initIssueApp } from '~/issues/show';
import * as parseData from '~/issues/show/utils/parse_data';
import axios from '~/lib/utils/axios_utils';
import createStore from '~/notes/stores';
......@@ -17,7 +17,7 @@ const setupHTML = (initialData) => {
};
describe('Issue show index', () => {
describe('initIssuableApp', () => {
describe('initIssueApp', () => {
it('should initialize app with no potential XSS attack', async () => {
const alertSpy = jest.spyOn(window, 'alert').mockImplementation(() => {});
const parseDataSpy = jest.spyOn(parseData, 'parseIssuableData');
......@@ -29,7 +29,7 @@ describe('Issue show index', () => {
const initialDataEl = document.getElementById('js-issuable-app');
const issuableData = parseData.parseIssuableData(initialDataEl);
initIssuableApp(issuableData, createStore());
initIssueApp(issuableData, createStore());
await waitForPromises();
......
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