export const initSidebarTracking = () => {};
export const trackEvent = () => {};
// Noop function which has a EE counter-part
export default () => {};
...@@ -22,7 +22,6 @@ export default class FilterableList { ...@@ -22,7 +22,6 @@ export default class FilterableList {
getPagePath() { getPagePath() {
const action = this.filterForm.getAttribute('action'); const action = this.filterForm.getAttribute('action');
// eslint-disable-next-line no-jquery/no-serialize
const params = $(this.filterForm).serialize(); const params = $(this.filterForm).serialize();
return `${action}${action.indexOf('?') > 0 ? '&' : '?'}${params}`; return `${action}${action.indexOf('?') > 0 ? '&' : '?'}${params}`;
} }
... ...
......
...@@ -15,10 +15,11 @@ import { parseBoolean } from '~/lib/utils/common_utils'; ...@@ -15,10 +15,11 @@ import { parseBoolean } from '~/lib/utils/common_utils';
*/ */
export default function initTodoToggle() { export default function initTodoToggle() {
$(document).on('todo:toggle', (e, count) => { $(document).on('todo:toggle', (e, count) => {
const parsedCount = parseInt(count, 10);
const $todoPendingCount = $('.todos-count'); const $todoPendingCount = $('.todos-count');
$todoPendingCount.text(highCountTrim(count)); $todoPendingCount.text(highCountTrim(parsedCount));
$todoPendingCount.toggleClass('hidden', count === 0); $todoPendingCount.toggleClass('hidden', parsedCount === 0);
}); });
} }
... ...
......
...@@ -3,7 +3,7 @@ import $ from 'jquery'; ...@@ -3,7 +3,7 @@ import $ from 'jquery';
import { mapActions } from 'vuex'; import { mapActions } from 'vuex';
import { __, sprintf } from '~/locale'; import { __, sprintf } from '~/locale';
import Icon from '~/vue_shared/components/icon.vue'; import Icon from '~/vue_shared/components/icon.vue';
import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue'; import GlModal from '~/vue_shared/components/gl_modal.vue';
import tooltip from '~/vue_shared/directives/tooltip'; import tooltip from '~/vue_shared/directives/tooltip';
import ListItem from './list_item.vue'; import ListItem from './list_item.vue';
...@@ -11,7 +11,7 @@ export default { ...@@ -11,7 +11,7 @@ export default {
components: { components: {
Icon, Icon,
ListItem, ListItem,
GlModal: DeprecatedModal2, GlModal,
}, },
directives: { directives: {
tooltip, tooltip,
... ...
......
...@@ -4,12 +4,12 @@ import { mapActions } from 'vuex'; ...@@ -4,12 +4,12 @@ import { mapActions } from 'vuex';
import { sprintf, __ } from '~/locale'; import { sprintf, __ } from '~/locale';
import Icon from '~/vue_shared/components/icon.vue'; import Icon from '~/vue_shared/components/icon.vue';
import tooltip from '~/vue_shared/directives/tooltip'; import tooltip from '~/vue_shared/directives/tooltip';
import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue'; import GlModal from '~/vue_shared/components/gl_modal.vue';
export default { export default {
components: { components: {
Icon, Icon,
GlModal: DeprecatedModal2, GlModal,
}, },
directives: { directives: {
tooltip, tooltip,
... ...
......
...@@ -3,12 +3,12 @@ import $ from 'jquery'; ...@@ -3,12 +3,12 @@ import $ from 'jquery';
import flash from '~/flash'; import flash from '~/flash';
import { __, sprintf, s__ } from '~/locale'; import { __, sprintf, s__ } from '~/locale';
import { mapActions, mapState, mapGetters } from 'vuex'; import { mapActions, mapState, mapGetters } from 'vuex';
import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue'; import GlModal from '~/vue_shared/components/gl_modal.vue';
import { modalTypes } from '../../constants'; import { modalTypes } from '../../constants';
export default { export default {
components: { components: {
GlModal: DeprecatedModal2, GlModal,
}, },
data() { data() {
return { return {
... ...
......
import { spriteIcon } from '~/lib/utils/common_utils';
export function createImageBadge(noteId, { x, y }, classNames = []) { export function createImageBadge(noteId, { x, y }, classNames = []) {
const buttonEl = document.createElement('button'); const buttonEl = document.createElement('button');
const classList = classNames.concat(['js-image-badge']); const classList = classNames.concat(['js-image-badge']);
...@@ -22,7 +20,7 @@ export function addImageBadge(containerEl, { coordinate, badgeText, noteId }) { ...@@ -22,7 +20,7 @@ export function addImageBadge(containerEl, { coordinate, badgeText, noteId }) {
export function addImageCommentBadge(containerEl, { coordinate, noteId }) { export function addImageCommentBadge(containerEl, { coordinate, noteId }) {
const buttonEl = createImageBadge(noteId, coordinate, ['image-comment-badge']); const buttonEl = createImageBadge(noteId, coordinate, ['image-comment-badge']);
buttonEl.innerHTML = spriteIcon('image-comment-dark'); buttonEl.innerHTML = gl.utils.spriteIcon('image-comment-dark');
containerEl.appendChild(buttonEl); containerEl.appendChild(buttonEl);
} }
... ...
......
import { spriteIcon } from '~/lib/utils/common_utils';
export function addCommentIndicator(containerEl, { x, y }) { export function addCommentIndicator(containerEl, { x, y }) {
const buttonEl = document.createElement('button'); const buttonEl = document.createElement('button');
buttonEl.classList.add('btn-transparent'); buttonEl.classList.add('btn-transparent');
...@@ -8,7 +6,7 @@ export function addCommentIndicator(containerEl, { x, y }) { ...@@ -8,7 +6,7 @@ export function addCommentIndicator(containerEl, { x, y }) {
buttonEl.style.left = `${x}px`; buttonEl.style.left = `${x}px`;
buttonEl.style.top = `${y}px`; buttonEl.style.top = `${y}px`;
buttonEl.innerHTML = spriteIcon('image-comment-dark'); buttonEl.innerHTML = gl.utils.spriteIcon('image-comment-dark');
containerEl.appendChild(buttonEl); containerEl.appendChild(buttonEl);
} }
... ...
......
<script> <script>
import _ from 'underscore';
import { mapActions, mapState, mapGetters } from 'vuex'; import { mapActions, mapState, mapGetters } from 'vuex';
import { GlLoadingIcon } from '@gitlab/ui'; import { GlLoadingIcon } from '@gitlab/ui';
import LoadingButton from '~/vue_shared/components/loading_button.vue'; import LoadingButton from '~/vue_shared/components/loading_button.vue';
...@@ -8,8 +7,6 @@ import ImportedProjectTableRow from './imported_project_table_row.vue'; ...@@ -8,8 +7,6 @@ import ImportedProjectTableRow from './imported_project_table_row.vue';
import ProviderRepoTableRow from './provider_repo_table_row.vue'; import ProviderRepoTableRow from './provider_repo_table_row.vue';
import eventHub from '../event_hub'; import eventHub from '../event_hub';
const reposFetchThrottleDelay = 1000;
export default { export default {
name: 'ImportProjectsTable', name: 'ImportProjectsTable',
components: { components: {
...@@ -26,11 +23,11 @@ export default { ...@@ -26,11 +23,11 @@ export default {
}, },
computed: { computed: {
...mapState(['importedProjects', 'providerRepos', 'isLoadingRepos', 'filter']), ...mapState(['importedProjects', 'providerRepos', 'isLoadingRepos']),
...mapGetters(['isImportingAnyRepo', 'hasProviderRepos', 'hasImportedProjects']), ...mapGetters(['isImportingAnyRepo', 'hasProviderRepos', 'hasImportedProjects']),
emptyStateText() { emptyStateText() {
return sprintf(__('No %{providerTitle} repositories found'), { return sprintf(__('No %{providerTitle} repositories available to import'), {
providerTitle: this.providerTitle, providerTitle: this.providerTitle,
}); });
}, },
...@@ -50,38 +47,21 @@ export default { ...@@ -50,38 +47,21 @@ export default {
}, },
methods: { methods: {
...mapActions([ ...mapActions(['fetchRepos', 'fetchJobs', 'stopJobsPolling', 'clearJobsEtagPoll']),
'fetchRepos',
'fetchReposFiltered',
'fetchJobs',
'stopJobsPolling',
'clearJobsEtagPoll',
'setFilter',
]),
importAll() { importAll() {
eventHub.$emit('importAll'); eventHub.$emit('importAll');
}, },
handleFilterInput({ target }) {
this.setFilter(target.value);
},
throttledFetchRepos: _.throttle(function fetch() {
eventHub.$off('importAll');
this.fetchRepos();
}, reposFetchThrottleDelay),
}, },
}; };
</script> </script>
<template> <template>
<div> <div>
<p class="light text-nowrap mt-2"> <div class="d-flex justify-content-between align-items-end flex-wrap mb-3">
<p class="light text-nowrap mt-2 my-sm-0">
{{ s__('ImportProjects|Select the projects you want to import') }} {{ s__('ImportProjects|Select the projects you want to import') }}
</p> </p>
<div class="d-flex justify-content-between align-items-end flex-wrap mb-3">
<loading-button <loading-button
container-class="btn btn-success js-import-all" container-class="btn btn-success js-import-all"
:loading="isImportingAnyRepo" :loading="isImportingAnyRepo"
...@@ -90,19 +70,6 @@ export default { ...@@ -90,19 +70,6 @@ export default {
type="button" type="button"
@click="importAll" @click="importAll"
/> />
<form novalidate @submit.prevent>
<input
:value="filter"
data-qa-selector="githubish_import_filter_field"
class="form-control"
name="filter"
:placeholder="__('Filter your projects by name')"
autofocus
size="40"
@input="handleFilterInput($event)"
@keyup.enter="throttledFetchRepos"
/>
</form>
</div> </div>
<gl-loading-icon <gl-loading-icon
v-if="isLoadingRepos" v-if="isLoadingRepos"
... ...
......
...@@ -38,7 +38,7 @@ export default function mountImportProjectsTable(mountElement) { ...@@ -38,7 +38,7 @@ export default function mountImportProjectsTable(mountElement) {
}, },
methods: { methods: {
...mapActions(['setInitialData', 'setFilter']), ...mapActions(['setInitialData']),
}, },
render(createElement) { render(createElement) {
... ...
......
...@@ -5,7 +5,6 @@ import Poll from '~/lib/utils/poll'; ...@@ -5,7 +5,6 @@ import Poll from '~/lib/utils/poll';
import createFlash from '~/flash'; import createFlash from '~/flash';
import { s__, sprintf } from '~/locale'; import { s__, sprintf } from '~/locale';
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import { jobsPathWithFilter, reposPathWithFilter } from './getters';
let eTagPoll; let eTagPoll;
...@@ -20,20 +19,16 @@ export const restartJobsPolling = () => { ...@@ -20,20 +19,16 @@ export const restartJobsPolling = () => {
}; };
export const setInitialData = ({ commit }, data) => commit(types.SET_INITIAL_DATA, data); export const setInitialData = ({ commit }, data) => commit(types.SET_INITIAL_DATA, data);
export const setFilter = ({ commit }, filter) => commit(types.SET_FILTER, filter);
export const requestRepos = ({ commit }, repos) => commit(types.REQUEST_REPOS, repos); export const requestRepos = ({ commit }, repos) => commit(types.REQUEST_REPOS, repos);
export const receiveReposSuccess = ({ commit }, repos) => export const receiveReposSuccess = ({ commit }, repos) =>
commit(types.RECEIVE_REPOS_SUCCESS, repos); commit(types.RECEIVE_REPOS_SUCCESS, repos);
export const receiveReposError = ({ commit }) => commit(types.RECEIVE_REPOS_ERROR); export const receiveReposError = ({ commit }) => commit(types.RECEIVE_REPOS_ERROR);
export const fetchRepos = ({ state, dispatch }) => { export const fetchRepos = ({ state, dispatch }) => {
dispatch('stopJobsPolling');
dispatch('requestRepos'); dispatch('requestRepos');
const { provider } = state;
return axios return axios
.get(reposPathWithFilter(state)) .get(state.reposPath)
.then(({ data }) => .then(({ data }) =>
dispatch('receiveReposSuccess', convertObjectPropsToCamelCase(data, { deep: true })), dispatch('receiveReposSuccess', convertObjectPropsToCamelCase(data, { deep: true })),
) )
...@@ -41,7 +36,7 @@ export const fetchRepos = ({ state, dispatch }) => { ...@@ -41,7 +36,7 @@ export const fetchRepos = ({ state, dispatch }) => {
.catch(() => { .catch(() => {
createFlash( createFlash(
sprintf(s__('ImportProjects|Requesting your %{provider} repositories failed'), { sprintf(s__('ImportProjects|Requesting your %{provider} repositories failed'), {
provider, provider: state.provider,
}), }),
); );
...@@ -82,23 +77,16 @@ export const fetchImport = ({ state, dispatch }, { newName, targetNamespace, rep ...@@ -82,23 +77,16 @@ export const fetchImport = ({ state, dispatch }, { newName, targetNamespace, rep
export const receiveJobsSuccess = ({ commit }, updatedProjects) => export const receiveJobsSuccess = ({ commit }, updatedProjects) =>
commit(types.RECEIVE_JOBS_SUCCESS, updatedProjects); commit(types.RECEIVE_JOBS_SUCCESS, updatedProjects);
export const fetchJobs = ({ state, dispatch }) => { export const fetchJobs = ({ state, dispatch }) => {
const { filter } = state; if (eTagPoll) return;
if (eTagPoll) {
stopJobsPolling();
clearJobsEtagPoll();
}
eTagPoll = new Poll({ eTagPoll = new Poll({
resource: { resource: {
fetchJobs: () => axios.get(jobsPathWithFilter(state)), fetchJobs: () => axios.get(state.jobsPath),
}, },
method: 'fetchJobs', method: 'fetchJobs',
successCallback: ({ data }) => successCallback: ({ data }) =>
dispatch('receiveJobsSuccess', convertObjectPropsToCamelCase(data, { deep: true })), dispatch('receiveJobsSuccess', convertObjectPropsToCamelCase(data, { deep: true })),
errorCallback: () => errorCallback: () => createFlash(s__('ImportProjects|Updating the imported projects failed')),
createFlash(s__('ImportProjects|Update of imported projects with realtime changes failed')),
data: { filter },
}); });
if (!Visibility.hidden()) { if (!Visibility.hidden()) {
... ...
......
...@@ -20,8 +20,3 @@ export const isImportingAnyRepo = state => state.reposBeingImported.length > 0; ...@@ -20,8 +20,3 @@ export const isImportingAnyRepo = state => state.reposBeingImported.length > 0;
export const hasProviderRepos = state => state.providerRepos.length > 0; export const hasProviderRepos = state => state.providerRepos.length > 0;
export const hasImportedProjects = state => state.importedProjects.length > 0; export const hasImportedProjects = state => state.importedProjects.length > 0;
export const reposPathWithFilter = ({ reposPath, filter = '' }) =>
filter ? `${reposPath}?filter=${filter}` : reposPath;
export const jobsPathWithFilter = ({ jobsPath, filter = '' }) =>
filter ? `${jobsPath}?filter=${filter}` : jobsPath;
...@@ -9,5 +9,3 @@ export const RECEIVE_IMPORT_SUCCESS = 'RECEIVE_IMPORT_SUCCESS'; ...@@ -9,5 +9,3 @@ export const RECEIVE_IMPORT_SUCCESS = 'RECEIVE_IMPORT_SUCCESS';
export const RECEIVE_IMPORT_ERROR = 'RECEIVE_IMPORT_ERROR'; export const RECEIVE_IMPORT_ERROR = 'RECEIVE_IMPORT_ERROR';
export const RECEIVE_JOBS_SUCCESS = 'RECEIVE_JOBS_SUCCESS'; export const RECEIVE_JOBS_SUCCESS = 'RECEIVE_JOBS_SUCCESS';
export const SET_FILTER = 'SET_FILTER';
...@@ -6,10 +6,6 @@ export default { ...@@ -6,10 +6,6 @@ export default {
Object.assign(state, data); Object.assign(state, data);
}, },
[types.SET_FILTER](state, filter) {
state.filter = filter;
},
[types.REQUEST_REPOS](state) { [types.REQUEST_REPOS](state) {
state.isLoadingRepos = true; state.isLoadingRepos = true;
}, },
... ...
......
...@@ -12,5 +12,4 @@ export default () => ({ ...@@ -12,5 +12,4 @@ export default () => ({
isLoadingRepos: false, isLoadingRepos: false,
canSelectNamespace: false, canSelectNamespace: false,
ciCdOnly: false, ciCdOnly: false,
filter: '',
}); });
...@@ -42,7 +42,6 @@ export default class IntegrationSettingsForm { ...@@ -42,7 +42,6 @@ export default class IntegrationSettingsForm {
// and test the service using provided configuration. // and test the service using provided configuration.
if (this.$form.get(0).checkValidity() && this.canTestService) { if (this.$form.get(0).checkValidity() && this.canTestService) {
e.preventDefault(); e.preventDefault();
// eslint-disable-next-line no-jquery/no-serialize
this.testSettings(this.$form.serialize()); this.testSettings(this.$form.serialize());
} }
} }
... ...
......
...@@ -102,10 +102,10 @@ export default { ...@@ -102,10 +102,10 @@ export default {
required: false, required: false,
default: '', default: '',
}, },
issuableTemplateNamesPath: { issuableTemplates: {
type: String, type: Array,
required: false, required: false,
default: '', default: () => [],
}, },
markdownPreviewPath: { markdownPreviewPath: {
type: String, type: String,
...@@ -156,13 +156,9 @@ export default { ...@@ -156,13 +156,9 @@ export default {
store, store,
state: store.state, state: store.state,
showForm: false, showForm: false,
templatesRequested: false,
}; };
}, },
computed: { computed: {
issuableTemplates() {
return this.store.formState.issuableTemplates;
},
formState() { formState() {
return this.store.formState; return this.store.formState;
}, },
...@@ -237,7 +233,6 @@ export default { ...@@ -237,7 +233,6 @@ export default {
} }
return undefined; return undefined;
}, },
updateStoreState() { updateStoreState() {
return this.service return this.service
.getData() .getData()
...@@ -250,7 +245,7 @@ export default { ...@@ -250,7 +245,7 @@ export default {
}); });
}, },
updateAndShowForm(templates = []) { openForm() {
if (!this.showForm) { if (!this.showForm) {
this.showForm = true; this.showForm = true;
this.store.setFormState({ this.store.setFormState({
...@@ -259,32 +254,9 @@ export default { ...@@ -259,32 +254,9 @@ export default {
lock_version: this.state.lock_version, lock_version: this.state.lock_version,
lockedWarningVisible: false, lockedWarningVisible: false,
updateLoading: false, updateLoading: false,
issuableTemplates: templates,
});
}
},
requestTemplatesAndShowForm() {
return this.service
.loadTemplates(this.issuableTemplateNamesPath)
.then(res => {
this.updateAndShowForm(res.data);
})
.catch(() => {
createFlash(this.defaultErrorMessage);
this.updateAndShowForm();
}); });
},
openForm() {
if (!this.templatesRequested) {
this.templatesRequested = true;
this.requestTemplatesAndShowForm();
} else {
this.updateAndShowForm(this.issuableTemplates);
} }
}, },
closeForm() { closeForm() {
this.showForm = false; this.showForm = false;
}, },
... ...
......
import Vue from 'vue'; import Vue from 'vue';
import { initSidebarTracking } from 'ee_else_ce/event_tracking/issue_sidebar';
import issuableApp from './components/app.vue'; import issuableApp from './components/app.vue';
import { parseIssuableData } from './utils/parse_data'; import { parseIssuableData } from './utils/parse_data';
import '../vue_shared/vue_resource_interceptor';
export default function initIssueableApp() { export default function initIssueableApp() {
return new Vue({ return new Vue({
...@@ -8,6 +10,9 @@ export default function initIssueableApp() { ...@@ -8,6 +10,9 @@ export default function initIssueableApp() {
components: { components: {
issuableApp, issuableApp,
}, },
mounted() {
initSidebarTracking();
},
render(createElement) { render(createElement) {
return createElement('issuable-app', { return createElement('issuable-app', {
props: parseIssuableData(), props: parseIssuableData(),
... ...
......
...@@ -17,13 +17,4 @@ export default class Service { ...@@ -17,13 +17,4 @@ export default class Service {
updateIssuable(data) { updateIssuable(data) {
return axios.put(this.endpoint, data); return axios.put(this.endpoint, data);
} }
// eslint-disable-next-line class-methods-use-this
loadTemplates(templateNamesEndpoint) {
if (!templateNamesEndpoint) {
return Promise.resolve([]);
}
return axios.get(templateNamesEndpoint);
}
} }