Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilipa Lacerda <filipa@gitlab.com>2018-06-26 15:29:06 +0300
committerFilipa Lacerda <filipa@gitlab.com>2018-06-26 16:31:31 +0300
commit1b617fa677c59e228d0335cef78907fda77143a0 (patch)
tree5ac4579b5e5fafa57259d0dab6559f0691da3aa6 /app/assets/javascripts/boards/components/modal
parent4830c0c723b04ccd369fdc552498f74e4f09751b (diff)
Moves boards components into a .vue file
Diffstat (limited to 'app/assets/javascripts/boards/components/modal')
-rw-r--r--app/assets/javascripts/boards/components/modal/header.js79
-rw-r--r--app/assets/javascripts/boards/components/modal/header.vue82
-rw-r--r--app/assets/javascripts/boards/components/modal/index.js171
-rw-r--r--app/assets/javascripts/boards/components/modal/index.vue178
-rw-r--r--app/assets/javascripts/boards/components/modal/list.js159
-rw-r--r--app/assets/javascripts/boards/components/modal/list.vue162
6 files changed, 422 insertions, 409 deletions
diff --git a/app/assets/javascripts/boards/components/modal/header.js b/app/assets/javascripts/boards/components/modal/header.js
deleted file mode 100644
index cc9848058ca..00000000000
--- a/app/assets/javascripts/boards/components/modal/header.js
+++ /dev/null
@@ -1,79 +0,0 @@
-import Vue from 'vue';
-import modalFilters from './filters';
-import modalTabs from './tabs.vue';
-import ModalStore from '../../stores/modal_store';
-import modalMixin from '../../mixins/modal_mixins';
-
-gl.issueBoards.ModalHeader = Vue.extend({
- components: {
- modalTabs,
- modalFilters,
- },
- mixins: [modalMixin],
- props: {
- projectId: {
- type: Number,
- required: true,
- },
- milestonePath: {
- type: String,
- 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.blur();
-
- ModalStore.toggleAll();
- },
- },
- template: `
- <div>
- <header class="add-issues-header form-actions">
- <h2>
- Add issues
- <button
- type="button"
- class="close"
- data-dismiss="modal"
- aria-label="Close"
- @click="toggleModal(false)">
- <span aria-hidden="true">×</span>
- </button>
- </h2>
- </header>
- <modal-tabs v-if="!loading && issuesCount > 0"></modal-tabs>
- <div
- class="add-issues-search append-bottom-10"
- v-if="showSearch">
- <modal-filters :store="filter" />
- <button
- type="button"
- class="btn btn-success btn-inverted prepend-left-10"
- ref="selectAllBtn"
- @click="toggleAll">
- {{ selectAllText }}
- </button>
- </div>
- </div>
- `,
-});
diff --git a/app/assets/javascripts/boards/components/modal/header.vue b/app/assets/javascripts/boards/components/modal/header.vue
new file mode 100644
index 00000000000..979fb4d7199
--- /dev/null
+++ b/app/assets/javascripts/boards/components/modal/header.vue
@@ -0,0 +1,82 @@
+<script>
+ import ModalFilters from './filters';
+ import ModalTabs from './tabs.vue';
+ import ModalStore from '../../stores/modal_store';
+ import modalMixin from '../../mixins/modal_mixins';
+
+ export default {
+ components: {
+ ModalTabs,
+ ModalFilters,
+ },
+ mixins: [modalMixin],
+ props: {
+ projectId: {
+ type: Number,
+ required: true,
+ },
+ milestonePath: {
+ type: String,
+ 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.blur();
+
+ ModalStore.toggleAll();
+ },
+ },
+ };
+</script>
+<template>
+ <div>
+ <header class="add-issues-header form-actions">
+ <h2>
+ Add issues
+ <button
+ type="button"
+ class="close"
+ data-dismiss="modal"
+ aria-label="Close"
+ @click="toggleModal(false)"
+ >
+ <span aria-hidden="true">×</span>
+ </button>
+ </h2>
+ </header>
+ <modal-tabs v-if="!loading && issuesCount > 0"/>
+ <div
+ v-if="showSearch"
+ class="add-issues-search append-bottom-10">
+ <modal-filters :store="filter" />
+ <button
+ ref="selectAllBtn"
+ type="button"
+ class="btn btn-success btn-inverted prepend-left-10"
+ @click="toggleAll"
+ >
+ {{ selectAllText }}
+ </button>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/boards/components/modal/index.js b/app/assets/javascripts/boards/components/modal/index.js
deleted file mode 100644
index 983061f52ae..00000000000
--- a/app/assets/javascripts/boards/components/modal/index.js
+++ /dev/null
@@ -1,171 +0,0 @@
-/* global ListIssue */
-
-import Vue from 'vue';
-import queryData from '~/boards/utils/query_data';
-import loadingIcon from '~/vue_shared/components/loading_icon.vue';
-import './header';
-import './list';
-import ModalFooter from './footer.vue';
-import EmptyState from './empty_state.vue';
-import ModalStore from '../../stores/modal_store';
-
-gl.issueBoards.IssuesModal = Vue.extend({
- components: {
- EmptyState,
- 'modal-header': gl.issueBoards.ModalHeader,
- 'modal-list': gl.issueBoards.ModalList,
- ModalFooter,
- loadingIcon,
- },
- props: {
- newIssuePath: {
- type: String,
- required: true,
- },
- emptyStateSvg: {
- type: String,
- required: true,
- },
- issueLinkBase: {
- type: String,
- required: true,
- },
- rootPath: {
- type: String,
- required: true,
- },
- projectId: {
- type: Number,
- required: true,
- },
- milestonePath: {
- type: String,
- 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 gl.boardService.getBacklog(queryData(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 = !!foundSelectedIssue;
-
- this.issues.push(issue);
- });
-
- this.loadingNewPage = false;
-
- if (!this.issuesCount) {
- this.issuesCount = data.size;
- }
- }).catch(() => {
- // TODO: handle request error
- });
- },
- },
- template: `
- <div
- class="add-issues-modal"
- v-if="showAddIssuesModal">
- <div class="add-issues-container">
- <modal-header
- :project-id="projectId"
- :milestone-path="milestonePath"
- :label-path="labelPath">
- </modal-header>
- <modal-list
- :issue-link-base="issueLinkBase"
- :root-path="rootPath"
- :empty-state-svg="emptyStateSvg"
- v-if="!loading && showList && !filterLoading"></modal-list>
- <empty-state
- v-if="showEmptyState"
- :new-issue-path="newIssuePath"
- :empty-state-svg="emptyStateSvg"></empty-state>
- <section
- class="add-issues-list text-center"
- v-if="loading || filterLoading">
- <div class="add-issues-list-loading">
- <loading-icon />
- </div>
- </section>
- <modal-footer></modal-footer>
- </div>
- </div>
- `,
-});
diff --git a/app/assets/javascripts/boards/components/modal/index.vue b/app/assets/javascripts/boards/components/modal/index.vue
new file mode 100644
index 00000000000..33e72a6782e
--- /dev/null
+++ b/app/assets/javascripts/boards/components/modal/index.vue
@@ -0,0 +1,178 @@
+<script>
+ /* global ListIssue */
+ import queryData from '~/boards/utils/query_data';
+ import loadingIcon from '~/vue_shared/components/loading_icon.vue';
+ import ModalHeader from './header.vue';
+ import ModalList from './list.vue';
+ import ModalFooter from './footer.vue';
+ import EmptyState from './empty_state.vue';
+ import ModalStore from '../../stores/modal_store';
+
+ export default {
+ components: {
+ EmptyState,
+ ModalHeader,
+ ModalList,
+ ModalFooter,
+ loadingIcon,
+ },
+ props: {
+ newIssuePath: {
+ type: String,
+ required: true,
+ },
+ emptyStateSvg: {
+ type: String,
+ required: true,
+ },
+ issueLinkBase: {
+ type: String,
+ required: true,
+ },
+ rootPath: {
+ type: String,
+ required: true,
+ },
+ projectId: {
+ type: Number,
+ required: true,
+ },
+ milestonePath: {
+ type: String,
+ 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 gl.boardService
+ .getBacklog(
+ queryData(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 = !!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">
+ <div class="add-issues-container">
+ <modal-header
+ :project-id="projectId"
+ :milestone-path="milestonePath"
+ :label-path="labelPath"
+ />
+ <modal-list
+ v-if="!loading && showList && !filterLoading"
+ :issue-link-base="issueLinkBase"
+ :root-path="rootPath"
+ :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 text-center"
+ >
+ <div class="add-issues-list-loading">
+ <loading-icon />
+ </div>
+ </section>
+ <modal-footer/>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/boards/components/modal/list.js b/app/assets/javascripts/boards/components/modal/list.js
deleted file mode 100644
index 11061c72a7b..00000000000
--- a/app/assets/javascripts/boards/components/modal/list.js
+++ /dev/null
@@ -1,159 +0,0 @@
-import Vue from 'vue';
-import bp from '../../../breakpoints';
-import ModalStore from '../../stores/modal_store';
-
-gl.issueBoards.ModalList = Vue.extend({
- components: {
- 'issue-card-inner': gl.issueBoards.IssueCardInner,
- },
- props: {
- issueLinkBase: {
- type: String,
- required: true,
- },
- rootPath: {
- type: String,
- required: true,
- },
- 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 === 'lg' || breakpoint === 'md') {
- this.columns = 3;
- } else if (breakpoint === 'sm') {
- this.columns = 2;
- } else {
- this.columns = 1;
- }
- },
- },
- template: `
- <section
- class="add-issues-list add-issues-list-columns"
- ref="list">
- <div
- class="empty-state add-issues-empty-state-filter text-center"
- v-if="issuesCount > 0 && issues.length === 0">
- <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 in groupedIssues"
- class="add-issues-list-column">
- <div
- v-for="issue in group"
- v-if="showIssue(issue)"
- class="board-card-parent">
- <div
- class="board-card"
- :class="{ 'is-active': issue.selected }"
- @click="toggleIssue($event, issue)">
- <issue-card-inner
- :issue="issue"
- :issue-link-base="issueLinkBase"
- :root-path="rootPath">
- </issue-card-inner>
- <span
- :aria-label="'Issue #' + issue.id + ' selected'"
- aria-checked="true"
- v-if="issue.selected"
- class="issue-card-selected text-center">
- <i class="fa fa-check"></i>
- </span>
- </div>
- </div>
- </div>
- </section>
- `,
-});
diff --git a/app/assets/javascripts/boards/components/modal/list.vue b/app/assets/javascripts/boards/components/modal/list.vue
new file mode 100644
index 00000000000..02ac36d7367
--- /dev/null
+++ b/app/assets/javascripts/boards/components/modal/list.vue
@@ -0,0 +1,162 @@
+<script>
+ import bp from '../../../breakpoints';
+ import ModalStore from '../../stores/modal_store';
+ import IssueCardInner from '../issue_card_inner.vue';
+
+ export default {
+ components: {
+ IssueCardInner,
+ },
+ props: {
+ issueLinkBase: {
+ type: String,
+ required: true,
+ },
+ rootPath: {
+ type: String,
+ required: true,
+ },
+ 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 === 'lg' || breakpoint === 'md') {
+ this.columns = 3;
+ } else if (breakpoint === 'sm') {
+ this.columns = 2;
+ } else {
+ this.columns = 1;
+ }
+ },
+ },
+ };
+</script>
+<template>
+ <section
+ ref="list"
+ class="add-issues-list add-issues-list-columns">
+ <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"
+ @click="toggleIssue($event, issue)">
+ <issue-card-inner
+ :issue="issue"
+ :issue-link-base="issueLinkBase"
+ :root-path="rootPath"/>
+ <span
+ v-if="issue.selected"
+ :aria-label="'Issue #' + issue.id + ' selected'"
+ aria-checked="true"
+ class="issue-card-selected text-center">
+ <i class="fa fa-check"></i>
+ </span>
+ </div>
+ </div>
+ </div>
+ </section>
+</template>