debian-mirror-gitlab/app/assets/javascripts/boards/index.js

277 lines
8.2 KiB
JavaScript
Raw Normal View History

2018-05-09 12:01:36 +05:30
import $ from 'jquery';
2017-09-10 17:25:29 +05:30
import _ from 'underscore';
2017-08-17 22:00:37 +05:30
import Vue from 'vue';
2018-03-27 19:54:05 +05:30
import Flash from '~/flash';
import { __ } from '~/locale';
import '~/vue_shared/models/label';
2018-11-08 19:23:39 +05:30
import '~/vue_shared/models/assignee';
2018-03-27 19:54:05 +05:30
2017-08-17 22:00:37 +05:30
import FilteredSearchBoards from './filtered_search_boards';
import eventHub from './eventhub';
2018-12-05 23:21:45 +05:30
import sidebarEventHub from '~/sidebar/event_hub';
2017-09-10 17:25:29 +05:30
import './models/issue';
import './models/list';
import './models/milestone';
2018-03-27 19:54:05 +05:30
import './models/project';
2018-12-13 13:39:08 +05:30
import boardsStore from './stores/boards_store';
2018-10-15 14:42:47 +05:30
import ModalStore from './stores/modal_store';
2018-03-17 18:26:18 +05:30
import BoardService from './services/board_service';
2018-10-15 14:42:47 +05:30
import modalMixin from './mixins/modal_mixins';
2017-09-10 17:25:29 +05:30
import './filters/due_date_filters';
2018-12-13 13:39:08 +05:30
import Board from './components/board';
import BoardSidebar from './components/board_sidebar';
import initNewListDropdown from './components/new_list_dropdown';
2018-11-08 19:23:39 +05:30
import BoardAddIssuesModal from './components/modal/index.vue';
2018-12-05 23:21:45 +05:30
import '~/vue_shared/vue_resource_interceptor';
2019-07-31 22:56:46 +05:30
import {
NavigationType,
convertObjectPropsToCamelCase,
parseBoolean,
} from '~/lib/utils/common_utils';
2017-08-17 22:00:37 +05:30
2018-12-13 13:39:08 +05:30
let issueBoardsApp;
2018-03-27 19:54:05 +05:30
export default () => {
2017-08-17 22:00:37 +05:30
const $boardApp = document.getElementById('board-app');
2018-12-05 23:21:45 +05:30
// check for browser back and trigger a hard reload to circumvent browser caching.
2018-12-13 13:39:08 +05:30
window.addEventListener('pageshow', event => {
const isNavTypeBackForward =
window.performance && window.performance.navigation.type === NavigationType.TYPE_BACK_FORWARD;
2018-12-05 23:21:45 +05:30
if (event.persisted || isNavTypeBackForward) {
window.location.reload();
}
});
2018-12-13 13:39:08 +05:30
if (issueBoardsApp) {
issueBoardsApp.$destroy(true);
2017-08-17 22:00:37 +05:30
}
2018-12-13 13:39:08 +05:30
boardsStore.create();
2017-08-17 22:00:37 +05:30
2018-12-13 13:39:08 +05:30
issueBoardsApp = new Vue({
2017-08-17 22:00:37 +05:30
el: $boardApp,
components: {
2018-12-13 13:39:08 +05:30
Board,
BoardSidebar,
2018-11-08 19:23:39 +05:30
BoardAddIssuesModal,
2017-08-17 22:00:37 +05:30
},
data: {
2018-12-13 13:39:08 +05:30
state: boardsStore.state,
2017-08-17 22:00:37 +05:30
loading: true,
2018-03-17 18:26:18 +05:30
boardsEndpoint: $boardApp.dataset.boardsEndpoint,
2019-07-07 11:18:12 +05:30
recentBoardsEndpoint: $boardApp.dataset.recentBoardsEndpoint,
2018-03-17 18:26:18 +05:30
listsEndpoint: $boardApp.dataset.listsEndpoint,
2017-08-17 22:00:37 +05:30
boardId: $boardApp.dataset.boardId,
2019-02-15 15:39:39 +05:30
disabled: parseBoolean($boardApp.dataset.disabled),
2017-08-17 22:00:37 +05:30
issueLinkBase: $boardApp.dataset.issueLinkBase,
rootPath: $boardApp.dataset.rootPath,
bulkUpdatePath: $boardApp.dataset.bulkUpdatePath,
2018-12-13 13:39:08 +05:30
detailIssue: boardsStore.detail,
2017-08-17 22:00:37 +05:30
defaultAvatar: $boardApp.dataset.defaultAvatar,
},
computed: {
2018-11-18 11:00:15 +05:30
detailIssueVisible() {
2017-08-17 22:00:37 +05:30
return Object.keys(this.detailIssue.issue).length;
},
},
2018-11-18 11:00:15 +05:30
created() {
2018-03-17 18:26:18 +05:30
gl.boardService = new BoardService({
boardsEndpoint: this.boardsEndpoint,
2019-07-07 11:18:12 +05:30
recentBoardsEndpoint: this.recentBoardsEndpoint,
2018-03-17 18:26:18 +05:30
listsEndpoint: this.listsEndpoint,
bulkUpdatePath: this.bulkUpdatePath,
boardId: this.boardId,
});
2018-12-13 13:39:08 +05:30
boardsStore.rootPath = this.boardsEndpoint;
2017-08-17 22:00:37 +05:30
eventHub.$on('updateTokens', this.updateTokens);
2018-03-17 18:26:18 +05:30
eventHub.$on('newDetailIssue', this.updateDetailIssue);
eventHub.$on('clearDetailIssue', this.clearDetailIssue);
sidebarEventHub.$on('toggleSubscription', this.toggleSubscription);
2017-08-17 22:00:37 +05:30
},
beforeDestroy() {
eventHub.$off('updateTokens', this.updateTokens);
2018-03-17 18:26:18 +05:30
eventHub.$off('newDetailIssue', this.updateDetailIssue);
eventHub.$off('clearDetailIssue', this.clearDetailIssue);
sidebarEventHub.$off('toggleSubscription', this.toggleSubscription);
2017-08-17 22:00:37 +05:30
},
2018-11-18 11:00:15 +05:30
mounted() {
2018-12-13 13:39:08 +05:30
this.filterManager = new FilteredSearchBoards(boardsStore.filter, true, boardsStore.cantEdit);
2018-03-17 18:26:18 +05:30
this.filterManager.setup();
2018-12-13 13:39:08 +05:30
boardsStore.disabled = this.disabled;
2018-11-18 11:00:15 +05:30
gl.boardService
.all()
2018-03-17 18:26:18 +05:30
.then(res => res.data)
2018-11-18 11:00:15 +05:30
.then(data => {
data.forEach(board => {
2018-12-13 13:39:08 +05:30
const list = boardsStore.addList(board, this.defaultAvatar);
2017-08-17 22:00:37 +05:30
if (list.type === 'closed') {
list.position = Infinity;
2017-09-10 17:25:29 +05:30
} else if (list.type === 'backlog') {
list.position = -1;
2017-08-17 22:00:37 +05:30
}
});
this.state.lists = _.sortBy(this.state.lists, 'position');
2018-12-13 13:39:08 +05:30
boardsStore.addBlankState();
2017-08-17 22:00:37 +05:30
this.loading = false;
2017-09-10 17:25:29 +05:30
})
2018-03-17 18:26:18 +05:30
.catch(() => {
2019-07-31 22:56:46 +05:30
Flash(__('An error occurred while fetching the board lists. Please try again.'));
2018-03-17 18:26:18 +05:30
});
2017-08-17 22:00:37 +05:30
},
methods: {
updateTokens() {
this.filterManager.updateTokens();
2018-03-17 18:26:18 +05:30
},
updateDetailIssue(newIssue) {
2018-11-08 19:23:39 +05:30
const { sidebarInfoEndpoint } = newIssue;
2018-03-17 18:26:18 +05:30
if (sidebarInfoEndpoint && newIssue.subscribed === undefined) {
newIssue.setFetchingState('subscriptions', true);
BoardService.getIssueInfo(sidebarInfoEndpoint)
.then(res => res.data)
2018-11-18 11:00:15 +05:30
.then(data => {
2019-07-31 22:56:46 +05:30
const {
subscribed,
totalTimeSpent,
timeEstimate,
humanTimeEstimate,
humanTotalTimeSpent,
weight,
epic,
} = convertObjectPropsToCamelCase(data);
2018-03-17 18:26:18 +05:30
newIssue.setFetchingState('subscriptions', false);
newIssue.updateData({
2019-07-31 22:56:46 +05:30
humanTimeSpent: humanTotalTimeSpent,
timeSpent: totalTimeSpent,
humanTimeEstimate,
timeEstimate,
subscribed,
weight,
epic,
2018-03-17 18:26:18 +05:30
});
})
.catch(() => {
newIssue.setFetchingState('subscriptions', false);
Flash(__('An error occurred while fetching sidebar data'));
});
}
2018-12-13 13:39:08 +05:30
boardsStore.detail.issue = newIssue;
2018-03-17 18:26:18 +05:30
},
clearDetailIssue() {
2018-12-13 13:39:08 +05:30
boardsStore.detail.issue = {};
2018-03-17 18:26:18 +05:30
},
toggleSubscription(id) {
2018-12-13 13:39:08 +05:30
const { issue } = boardsStore.detail;
2018-03-17 18:26:18 +05:30
if (issue.id === id && issue.toggleSubscriptionEndpoint) {
issue.setFetchingState('subscriptions', true);
BoardService.toggleIssueSubscription(issue.toggleSubscriptionEndpoint)
.then(() => {
issue.setFetchingState('subscriptions', false);
issue.updateData({
subscribed: !issue.subscribed,
});
})
.catch(() => {
issue.setFetchingState('subscriptions', false);
Flash(__('An error occurred when toggling the notification subscription'));
});
}
2018-11-18 11:00:15 +05:30
},
2017-08-17 22:00:37 +05:30
},
});
2018-12-13 13:39:08 +05:30
// eslint-disable-next-line no-new
new Vue({
2017-08-17 22:00:37 +05:30
el: document.getElementById('js-add-list'),
data: {
2018-12-13 13:39:08 +05:30
filters: boardsStore.state.filters,
2017-08-17 22:00:37 +05:30
},
2018-11-18 11:00:15 +05:30
mounted() {
2018-12-13 13:39:08 +05:30
initNewListDropdown();
2018-03-17 18:26:18 +05:30
},
2017-08-17 22:00:37 +05:30
});
2018-11-18 11:00:15 +05:30
const issueBoardsModal = document.getElementById('js-add-issues-btn');
if (issueBoardsModal) {
2018-12-13 13:39:08 +05:30
// eslint-disable-next-line no-new
new Vue({
2018-11-18 11:00:15 +05:30
el: issueBoardsModal,
mixins: [modalMixin],
data() {
return {
modal: ModalStore.store,
2018-12-13 13:39:08 +05:30
store: boardsStore.state,
2018-11-18 11:00:15 +05:30
canAdminList: this.$options.el.hasAttribute('data-can-admin-list'),
};
2017-08-17 22:00:37 +05:30
},
2018-11-18 11:00:15 +05:30
computed: {
disabled() {
if (!this.store) {
return true;
}
return !this.store.lists.filter(list => !list.preset).length;
},
tooltipTitle() {
if (this.disabled) {
2019-07-31 22:56:46 +05:30
return __('Please add a list to your board first');
2018-11-18 11:00:15 +05:30
}
2017-08-17 22:00:37 +05:30
2018-11-18 11:00:15 +05:30
return '';
},
2017-08-17 22:00:37 +05:30
},
2018-11-18 11:00:15 +05:30
watch: {
disabled() {
this.updateTooltip();
},
},
mounted() {
2018-03-17 18:26:18 +05:30
this.updateTooltip();
},
2018-11-18 11:00:15 +05:30
methods: {
updateTooltip() {
const $tooltip = $(this.$refs.addIssuesButton);
this.$nextTick(() => {
if (this.disabled) {
$tooltip.tooltip();
} else {
$tooltip.tooltip('dispose');
}
});
},
openModal() {
if (!this.disabled) {
this.toggleModal(true);
2017-08-17 22:00:37 +05:30
}
2018-11-18 11:00:15 +05:30
},
2017-08-17 22:00:37 +05:30
},
2018-11-18 11:00:15 +05:30
template: `
<div class="board-extra-actions">
<button
2018-12-05 23:21:45 +05:30
class="btn btn-success prepend-left-10"
2018-11-18 11:00:15 +05:30
type="button"
data-placement="bottom"
ref="addIssuesButton"
:class="{ 'disabled': disabled }"
:title="tooltipTitle"
:aria-disabled="disabled"
v-if="canAdminList"
@click="openModal">
Add issues
</button>
</div>
`,
});
}
2018-03-27 19:54:05 +05:30
};