diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-04-21 02:50:22 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-04-21 02:50:22 +0300 |
commit | 9dc93a4519d9d5d7be48ff274127136236a3adb3 (patch) | |
tree | 70467ae3692a0e35e5ea56bcb803eb512a10bedb /app/assets/javascripts/boards/components/modal | |
parent | 4b0f34b6d759d6299322b3a54453e930c6121ff0 (diff) |
Add latest changes from gitlab-org/gitlab@13-11-stable-eev13.11.0-rc43
Diffstat (limited to 'app/assets/javascripts/boards/components/modal')
8 files changed, 0 insertions, 654 deletions
diff --git a/app/assets/javascripts/boards/components/modal/empty_state.vue b/app/assets/javascripts/boards/components/modal/empty_state.vue deleted file mode 100644 index 486b012e3d2..00000000000 --- a/app/assets/javascripts/boards/components/modal/empty_state.vue +++ /dev/null @@ -1,84 +0,0 @@ -<script> -import { GlButton, GlSprintf } from '@gitlab/ui'; -import { __ } from '~/locale'; -import modalMixin from '../../mixins/modal_mixins'; -import ModalStore from '../../stores/modal_store'; - -export default { - components: { - GlButton, - GlSprintf, - }, - mixins: [modalMixin], - props: { - newIssuePath: { - type: String, - required: true, - }, - emptyStateSvg: { - type: String, - required: true, - }, - }, - data() { - return ModalStore.store; - }, - computed: { - contents() { - const obj = { - title: __("You haven't added any issues to your project yet"), - content: __( - 'An issue can be a bug, a todo or a feature request that needs to be discussed in a project. Besides, issues are searchable and filterable.', - ), - }; - - if (this.activeTab === 'selected') { - obj.title = __("You haven't selected any issues yet"); - obj.content = __( - 'Go back to %{tagStart}Open issues%{tagEnd} and select some issues to add to your board.', - ); - } - - return obj; - }, - }, -}; -</script> - -<template> - <section class="empty-state d-flex mt-0 h-100"> - <div class="row w-100 my-auto mx-0"> - <div class="col-12 col-md-6 order-md-last"> - <aside class="svg-content d-none d-md-block"><img :src="emptyStateSvg" /></aside> - </div> - <div class="col-12 col-md-6 order-md-first"> - <div class="text-content"> - <h4>{{ contents.title }}</h4> - <p> - <gl-sprintf :message="contents.content"> - <template #tag="{ content }"> - <strong>{{ content }}</strong> - </template> - </gl-sprintf> - </p> - <gl-button - v-if="activeTab === 'all'" - :href="newIssuePath" - category="secondary" - variant="success" - > - {{ __('New issue') }} - </gl-button> - <gl-button - v-if="activeTab === 'selected'" - category="primary" - variant="default" - @click="changeTab('all')" - > - {{ __('Open issues') }} - </gl-button> - </div> - </div> - </div> - </section> -</template> diff --git a/app/assets/javascripts/boards/components/modal/filters.js b/app/assets/javascripts/boards/components/modal/filters.js deleted file mode 100644 index 2fb38a549f3..00000000000 --- a/app/assets/javascripts/boards/components/modal/filters.js +++ /dev/null @@ -1,27 +0,0 @@ -import FilteredSearchContainer from '../../../filtered_search/container'; -import FilteredSearchBoards from '../../filtered_search_boards'; - -export default { - name: 'modal-filters', - props: { - store: { - type: Object, - required: true, - }, - }, - mounted() { - FilteredSearchContainer.container = this.$el; - - this.filteredSearch = new FilteredSearchBoards(this.store); - this.filteredSearch.setup(); - this.filteredSearch.removeTokens(); - this.filteredSearch.handleInputPlaceholder(); - this.filteredSearch.toggleClearSearchButton(); - }, - destroyed() { - this.filteredSearch.cleanup(); - FilteredSearchContainer.container = document; - this.store.path = ''; - }, - template: '#js-board-modal-filter', -}; diff --git a/app/assets/javascripts/boards/components/modal/footer.vue b/app/assets/javascripts/boards/components/modal/footer.vue deleted file mode 100644 index 05e1219bc70..00000000000 --- a/app/assets/javascripts/boards/components/modal/footer.vue +++ /dev/null @@ -1,80 +0,0 @@ -<script> -import { GlButton } from '@gitlab/ui'; -import footerEEMixin from 'ee_else_ce/boards/mixins/modal_footer'; -import { deprecatedCreateFlash as Flash } from '../../../flash'; -import { __, n__ } from '../../../locale'; -import modalMixin from '../../mixins/modal_mixins'; -import boardsStore from '../../stores/boards_store'; -import ModalStore from '../../stores/modal_store'; -import ListsDropdown from './lists_dropdown.vue'; - -export default { - components: { - ListsDropdown, - GlButton, - }, - mixins: [modalMixin, footerEEMixin], - data() { - return { - modal: ModalStore.store, - state: boardsStore.state, - }; - }, - computed: { - submitDisabled() { - return !ModalStore.selectedCount(); - }, - submitText() { - const count = ModalStore.selectedCount(); - if (!count) return __('Add issues'); - return n__(`Add %d issue`, `Add %d issues`, count); - }, - }, - methods: { - buildUpdateRequest(list) { - return { - add_label_ids: [list.label.id], - }; - }, - addIssues() { - const firstListIndex = 1; - const list = this.modal.selectedList || this.state.lists[firstListIndex]; - const selectedIssues = ModalStore.getSelectedIssues(); - const issueIds = selectedIssues.map((issue) => issue.id); - const req = this.buildUpdateRequest(list); - - // Post the data to the backend - boardsStore.bulkUpdate(issueIds, req).catch(() => { - Flash(__('Failed to update issues, please try again.')); - - selectedIssues.forEach((issue) => { - list.removeIssue(issue); - list.issuesSize -= 1; - }); - }); - - // Add the issues on the frontend - selectedIssues.forEach((issue) => { - list.addIssue(issue); - list.issuesSize += 1; - }); - - this.toggleModal(false); - }, - }, -}; -</script> -<template> - <footer class="form-actions add-issues-footer"> - <div class="float-left"> - <gl-button :disabled="submitDisabled" category="primary" variant="success" @click="addIssues"> - {{ submitText }} - </gl-button> - <span class="inline add-issues-footer-to-list">{{ __('to list') }}</span> - <lists-dropdown /> - </div> - <gl-button class="float-right" @click="toggleModal(false)"> - {{ __('Cancel') }} - </gl-button> - </footer> -</template> diff --git a/app/assets/javascripts/boards/components/modal/header.vue b/app/assets/javascripts/boards/components/modal/header.vue deleted file mode 100644 index c3a71e7177a..00000000000 --- a/app/assets/javascripts/boards/components/modal/header.vue +++ /dev/null @@ -1,80 +0,0 @@ -<script> -/* eslint-disable @gitlab/vue-require-i18n-strings */ -import { GlButton } from '@gitlab/ui'; -import { __ } from '~/locale'; -import modalMixin from '../../mixins/modal_mixins'; -import ModalStore from '../../stores/modal_store'; -import ModalFilters from './filters'; -import ModalTabs from './tabs.vue'; - -export default { - components: { - ModalTabs, - ModalFilters, - GlButton, - }, - mixins: [modalMixin], - props: { - projectId: { - type: Number, - required: true, - }, - labelPath: { - type: String, - required: true, - }, - }, - data() { - return ModalStore.store; - }, - computed: { - selectAllText() { - if (ModalStore.selectedCount() !== this.issues.length || this.issues.length === 0) { - return __('Select all'); - } - - return __('Deselect all'); - }, - showSearch() { - return this.activeTab === 'all' && !this.loading && this.issuesCount > 0; - }, - }, - methods: { - toggleAll() { - this.$refs.selectAllBtn.$el.blur(); - - ModalStore.toggleAll(); - }, - }, -}; -</script> -<template> - <div> - <header class="add-issues-header border-top-0 form-actions"> - <h2 class="m-0"> - Add issues - <gl-button - category="tertiary" - icon="close" - class="close" - data-dismiss="modal" - :aria-label="__('Close')" - @click="toggleModal(false)" - /> - </h2> - </header> - <modal-tabs v-if="!loading && issuesCount > 0" /> - <div v-if="showSearch" class="d-flex gl-mb-3"> - <modal-filters :store="filter" /> - <gl-button - ref="selectAllBtn" - category="secondary" - variant="success" - class="gl-ml-3" - @click="toggleAll" - > - {{ selectAllText }} - </gl-button> - </div> - </div> -</template> diff --git a/app/assets/javascripts/boards/components/modal/index.vue b/app/assets/javascripts/boards/components/modal/index.vue deleted file mode 100644 index 5af90c1ee66..00000000000 --- a/app/assets/javascripts/boards/components/modal/index.vue +++ /dev/null @@ -1,151 +0,0 @@ -<script> -/* global ListIssue */ -import { GlLoadingIcon } from '@gitlab/ui'; -import boardsStore from '~/boards/stores/boards_store'; -import { urlParamsToObject } from '~/lib/utils/common_utils'; -import ModalStore from '../../stores/modal_store'; -import EmptyState from './empty_state.vue'; -import ModalFooter from './footer.vue'; -import ModalHeader from './header.vue'; -import ModalList from './list.vue'; - -export default { - components: { - EmptyState, - ModalHeader, - ModalList, - ModalFooter, - GlLoadingIcon, - }, - props: { - newIssuePath: { - type: String, - required: true, - }, - emptyStateSvg: { - type: String, - required: true, - }, - projectId: { - type: Number, - required: true, - }, - labelPath: { - type: String, - required: true, - }, - }, - data() { - return ModalStore.store; - }, - computed: { - showList() { - if (this.activeTab === 'selected') { - return this.selectedIssues.length > 0; - } - - return this.issuesCount > 0; - }, - showEmptyState() { - if (!this.loading && this.issuesCount === 0) { - return true; - } - - return this.activeTab === 'selected' && this.selectedIssues.length === 0; - }, - }, - watch: { - page() { - this.loadIssues(); - }, - showAddIssuesModal() { - if (this.showAddIssuesModal && !this.issues.length) { - this.loading = true; - const loadingDone = () => { - this.loading = false; - }; - - this.loadIssues().then(loadingDone).catch(loadingDone); - } else if (!this.showAddIssuesModal) { - this.issues = []; - this.selectedIssues = []; - this.issuesCount = false; - } - }, - filter: { - handler() { - if (this.$el.tagName) { - this.page = 1; - this.filterLoading = true; - const loadingDone = () => { - this.filterLoading = false; - }; - - this.loadIssues(true).then(loadingDone).catch(loadingDone); - } - }, - deep: true, - }, - }, - created() { - this.page = 1; - }, - methods: { - loadIssues(clearIssues = false) { - if (!this.showAddIssuesModal) return false; - - return boardsStore - .getBacklog({ - ...urlParamsToObject(this.filter.path), - page: this.page, - per: this.perPage, - }) - .then((res) => res.data) - .then((data) => { - if (clearIssues) { - this.issues = []; - } - - data.issues.forEach((issueObj) => { - const issue = new ListIssue(issueObj); - const foundSelectedIssue = ModalStore.findSelectedIssue(issue); - issue.selected = Boolean(foundSelectedIssue); - - this.issues.push(issue); - }); - - this.loadingNewPage = false; - - if (!this.issuesCount) { - this.issuesCount = data.size; - } - }) - .catch(() => { - // TODO: handle request error - }); - }, - }, -}; -</script> -<template> - <div - v-if="showAddIssuesModal" - class="add-issues-modal d-flex position-fixed position-top-0 position-bottom-0 position-left-0 position-right-0 h-100" - > - <div class="add-issues-container d-flex flex-column m-auto rounded"> - <modal-header :project-id="projectId" :label-path="labelPath" /> - <modal-list v-if="!loading && showList && !filterLoading" :empty-state-svg="emptyStateSvg" /> - <empty-state - v-if="showEmptyState" - :new-issue-path="newIssuePath" - :empty-state-svg="emptyStateSvg" - /> - <section v-if="loading || filterLoading" class="add-issues-list d-flex h-100 text-center"> - <div class="add-issues-list-loading w-100 align-self-center"> - <gl-loading-icon size="md" /> - </div> - </section> - <modal-footer /> - </div> - </div> -</template> diff --git a/app/assets/javascripts/boards/components/modal/list.vue b/app/assets/javascripts/boards/components/modal/list.vue deleted file mode 100644 index e66cae0ce18..00000000000 --- a/app/assets/javascripts/boards/components/modal/list.vue +++ /dev/null @@ -1,141 +0,0 @@ -<script> -import { GlIcon } from '@gitlab/ui'; -import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils'; -import ModalStore from '../../stores/modal_store'; -import BoardCardInner from '../board_card_inner.vue'; - -export default { - components: { - BoardCardInner, - GlIcon, - }, - props: { - emptyStateSvg: { - type: String, - required: true, - }, - }, - data() { - return ModalStore.store; - }, - computed: { - loopIssues() { - if (this.activeTab === 'all') { - return this.issues; - } - - return this.selectedIssues; - }, - groupedIssues() { - const groups = []; - this.loopIssues.forEach((issue, i) => { - const index = i % this.columns; - - if (!groups[index]) { - groups.push([]); - } - - groups[index].push(issue); - }); - - return groups; - }, - }, - watch: { - activeTab() { - if (this.activeTab === 'all') { - ModalStore.purgeUnselectedIssues(); - } - }, - }, - mounted() { - this.scrollHandlerWrapper = this.scrollHandler.bind(this); - this.setColumnCountWrapper = this.setColumnCount.bind(this); - this.setColumnCount(); - - this.$refs.list.addEventListener('scroll', this.scrollHandlerWrapper); - window.addEventListener('resize', this.setColumnCountWrapper); - }, - beforeDestroy() { - this.$refs.list.removeEventListener('scroll', this.scrollHandlerWrapper); - window.removeEventListener('resize', this.setColumnCountWrapper); - }, - methods: { - scrollHandler() { - const currentPage = Math.floor(this.issues.length / this.perPage); - - if ( - this.scrollTop() > this.scrollHeight() - 100 && - !this.loadingNewPage && - currentPage === this.page - ) { - this.loadingNewPage = true; - this.page += 1; - } - }, - toggleIssue(e, issue) { - if (e.target.tagName !== 'A') { - ModalStore.toggleIssue(issue); - } - }, - listHeight() { - return this.$refs.list.getBoundingClientRect().height; - }, - scrollHeight() { - return this.$refs.list.scrollHeight; - }, - scrollTop() { - return this.$refs.list.scrollTop + this.listHeight(); - }, - showIssue(issue) { - if (this.activeTab === 'all') return true; - - const index = ModalStore.selectedIssueIndex(issue); - - return index !== -1; - }, - setColumnCount() { - const breakpoint = bp.getBreakpointSize(); - - if (breakpoint === 'xl' || breakpoint === 'lg') { - this.columns = 3; - } else if (breakpoint === 'md') { - this.columns = 2; - } else { - this.columns = 1; - } - }, - }, -}; -</script> -<template> - <section ref="list" class="add-issues-list add-issues-list-columns d-flex h-100"> - <div - v-if="issuesCount > 0 && issues.length === 0" - class="empty-state add-issues-empty-state-filter text-center" - > - <div class="svg-content"><img :src="emptyStateSvg" /></div> - <div class="text-content"> - <h4>{{ __('There are no issues to show.') }}</h4> - </div> - </div> - <div v-for="(group, index) in groupedIssues" :key="index" class="add-issues-list-column"> - <div v-for="issue in group" v-if="showIssue(issue)" :key="issue.id" class="board-card-parent"> - <div - :class="{ 'is-active': issue.selected }" - class="board-card position-relative p-3 rounded" - @click="toggleIssue($event, issue)" - > - <board-card-inner :item="issue" /> - <gl-icon - v-if="issue.selected" - :aria-label="'Issue #' + issue.id + ' selected'" - name="mobile-issue-close" - aria-checked="true" - class="issue-card-selected text-center" - /> - </div> - </div> - </div> - </section> -</template> diff --git a/app/assets/javascripts/boards/components/modal/lists_dropdown.vue b/app/assets/javascripts/boards/components/modal/lists_dropdown.vue deleted file mode 100644 index 2065568d275..00000000000 --- a/app/assets/javascripts/boards/components/modal/lists_dropdown.vue +++ /dev/null @@ -1,49 +0,0 @@ -<script> -import { GlLink, GlIcon } from '@gitlab/ui'; -import boardsStore from '../../stores/boards_store'; -import ModalStore from '../../stores/modal_store'; - -export default { - components: { - GlLink, - GlIcon, - }, - data() { - return { - modal: ModalStore.store, - state: boardsStore.state, - }; - }, - computed: { - selected() { - return this.modal.selectedList || this.state.lists[1]; - }, - }, - destroyed() { - this.modal.selectedList = null; - }, -}; -</script> -<template> - <div class="dropdown inline"> - <button class="dropdown-menu-toggle" type="button" data-toggle="dropdown" aria-expanded="false"> - <span :style="{ backgroundColor: selected.label.color }" class="dropdown-label-box"> </span> - {{ selected.title }} <gl-icon name="chevron-down" class="dropdown-menu-toggle-icon" /> - </button> - <div class="dropdown-menu dropdown-menu-selectable dropdown-menu-drop-up"> - <ul> - <li v-for="(list, i) in state.lists" v-if="list.type == 'label'" :key="i"> - <gl-link - :class="{ 'is-active': list.id == selected.id }" - href="#" - role="button" - @click.prevent="modal.selectedList = list" - > - <span :style="{ backgroundColor: list.label.color }" class="dropdown-label-box"> </span> - {{ list.title }} - </gl-link> - </li> - </ul> - </div> - </div> -</template> diff --git a/app/assets/javascripts/boards/components/modal/tabs.vue b/app/assets/javascripts/boards/components/modal/tabs.vue deleted file mode 100644 index 0b717f516db..00000000000 --- a/app/assets/javascripts/boards/components/modal/tabs.vue +++ /dev/null @@ -1,42 +0,0 @@ -<script> -/* eslint-disable @gitlab/vue-require-i18n-strings */ -import { GlTabs, GlTab, GlBadge } from '@gitlab/ui'; -import modalMixin from '../../mixins/modal_mixins'; -import ModalStore from '../../stores/modal_store'; - -export default { - components: { - GlTabs, - GlTab, - GlBadge, - }, - mixins: [modalMixin], - data() { - return ModalStore.store; - }, - computed: { - selectedCount() { - return ModalStore.selectedCount(); - }, - }, - destroyed() { - this.activeTab = 'all'; - }, -}; -</script> -<template> - <gl-tabs class="gl-mt-3"> - <gl-tab @click.prevent="changeTab('all')"> - <template slot="title"> - <span>Open issues</span> - <gl-badge size="sm" class="gl-tab-counter-badge">{{ issuesCount }}</gl-badge> - </template> - </gl-tab> - <gl-tab @click.prevent="changeTab('selected')"> - <template slot="title"> - <span>Selected issues</span> - <gl-badge size="sm" class="gl-tab-counter-badge">{{ selectedCount }}</gl-badge> - </template> - </gl-tab> - </gl-tabs> -</template> |