Commit 51004d0e authored by Simon Knox's avatar Simon Knox

Merge branch 'issue-board-edit-modal' into edit-board

parents 0f1e3360 cc5e7b63
...@@ -148,12 +148,19 @@ $(() => { ...@@ -148,12 +148,19 @@ $(() => {
gl.boardConfigToggle = new Vue({ gl.boardConfigToggle = new Vue({
el: document.querySelector('.js-board-config'), el: document.querySelector('.js-board-config'),
data() {
return {
canAdminList: convertPermissionToBoolean(
this.$options.el.dataset.canAdminList,
),
};
},
methods: { methods: {
showPage: page => gl.issueBoards.BoardsStore.showPage(page), showPage: page => gl.issueBoards.BoardsStore.showPage(page),
}, },
computed: { computed: {
buttonText() { buttonText() {
return Math.random > 0.5 ? 'Edit board' : 'View scope'; return this.canAdminList ? 'Edit board' : 'View scope';
}, },
}, },
template: ` template: `
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
v-show="currentPage" v-show="currentPage"
:title="title" :title="title"
:primaryButtonLabel="buttonText" :primaryButtonLabel="buttonText"
:kind="buttonKind"
@toggle="cancel" @toggle="cancel"
@submit="submit" @submit="submit"
> >
...@@ -13,8 +14,11 @@ ...@@ -13,8 +14,11 @@
<form <form
v-else v-else
> >
<div class="append-bottom-20"> <div
<label class="label-light" for="board-new-name"> v-if="!readonly"
class="append-bottom-20"
>
<label class="form-section-title label-light" for="board-new-name">
Board name Board name
</label> </label>
<input <input
...@@ -24,19 +28,23 @@ ...@@ -24,19 +28,23 @@
v-model="board.name" v-model="board.name"
> >
</div> </div>
<div class="media append-bottom-10"> <div
<label class="label-light media-body"> v-if="canAdminBoard"
class="media append-bottom-10"
>
<label class="form-section-title label-light media-body">
Board scope Board scope
</label> </label>
<button <button
type="button" type="button"
class="btn" class="btn"
@click="expand = !expand" @click="expanded = !expanded"
v-if="collapseScope"
> >
Expand {{ expandButtonText }}
</button> </button>
</div> </div>
<div v-if="expand"> <div v-if="!collapseScope || expanded">
<p class="light append-bottom-10"> <p class="light append-bottom-10">
Board scope affects which issues are displayed for anyone who visits this board Board scope affects which issues are displayed for anyone who visits this board
</p> </p>
...@@ -45,47 +53,57 @@ ...@@ -45,47 +53,57 @@
<form-block <form-block
title="Milestone" title="Milestone"
defaultText="Any milestone" defaultText="Any milestone"
:canEdit="canAdminBoard"
> >
<input <div
type="hidden" v-if="board.milestone"
id="board-milestone" slot="currentValue"
v-model.number="board.milestone_id"
> >
{{ board.milestone.title }}
</div>
<board-milestone-select <board-milestone-select
:board="board" :board="board"
:milestone-path="milestonePath" :milestone-path="milestonePath"
:select-milestone="selectMilestone"> v-model="board.milestone">
</board-milestone-select> </board-milestone-select>
</form-block> </form-block>
<form-block <form-block
title="Labels" title="Labels"
defaultText="Any label" defaultText="Any label"
:canEdit="canAdminBoard"
> >
</form-block> </form-block>
<form-block <form-block
title="Assignee" title="Assignee"
defaultText="Any assignee" defaultText="Any assignee"
:fieldName="'filter[assignee]'" :fieldName="'board_filter[assignee]'"
:canEdit="canAdminBoard"
> >
</form-block> </form-block>
<form-block <form-block
title="Author" title="Author"
defaultText="Any author" defaultText="Any author"
:fieldName="'filter[author]'" :fieldName="'board_filter[author]'"
:canEdit="canAdminBoard"
> >
</form-block> </form-block>
<form-block <form-block
title="Weight" title="Weight"
defaultText="Any weight" defaultText="Any weight"
:fieldName="'filter[weight]'" :fieldName="'board_filter[weight]'"
:canEdit="canAdminBoard"
> >
</form-block> </form-block>
</div> </div>
</form> </form>
<div
slot="footer"
v-if="readonly"
></div>
</popup-dialog> </popup-dialog>
</template> </template>
...@@ -108,6 +126,10 @@ export default Vue.extend({ ...@@ -108,6 +126,10 @@ export default Vue.extend({
type: String, type: String,
required: true, required: true,
}, },
canAdminBoard: {
type: Boolean,
required: true,
},
}, },
data() { data() {
return { return {
...@@ -115,7 +137,7 @@ export default Vue.extend({ ...@@ -115,7 +137,7 @@ export default Vue.extend({
id: false, id: false,
name: '', name: '',
}, },
expand: false, expanded: false,
issue: {}, issue: {},
currentBoard: Store.state.currentBoard, currentBoard: Store.state.currentBoard,
currentPage: Store.state.currentPage, currentPage: Store.state.currentPage,
...@@ -139,14 +161,31 @@ export default Vue.extend({ ...@@ -139,14 +161,31 @@ export default Vue.extend({
return 'Create'; return 'Create';
} }
if (this.currentPage === 'delete') {
return 'Delete';
}
return 'Save'; return 'Save';
}, },
buttonKind() {
if (this.currentPage === 'delete') {
return 'danger';
}
return 'info';
},
title() { title() {
if (this.currentPage === 'new') { if (this.currentPage === 'new') {
return 'Create new board'; return 'Create new board';
} }
// TODO check for readonly if (this.currentPage === 'delete') {
return 'Delete board';
}
if (this.readonly) {
return 'Board scope';
}
return 'Edit board'; return 'Edit board';
}, },
milestoneToggleText() { milestoneToggleText() {
...@@ -155,6 +194,15 @@ export default Vue.extend({ ...@@ -155,6 +194,15 @@ export default Vue.extend({
submitDisabled() { submitDisabled() {
return false; return false;
}, },
expandButtonText() {
return this.expanded ? 'Collapse' : 'Expand'
},
collapseScope() {
return this.currentPage === 'new';
},
readonly() {
return !this.canAdminBoard;
},
}, },
methods: { methods: {
refreshPage() { refreshPage() {
......
<template>
<ul
ref="list"
class="dropdown-menu"
>
<slot name="items"></slot>
</ul>
</template>
<script>
import DropLab from '~/droplab/drop_lab';
export default {
props: {
},
data() {
return {
loading: false,
};
},
mounted() {
this.droplab = new DropLab();
this.droplab.init(this.$refs.trigger, this.$refs.list);
},
};
</script>
<template> <template>
<div class="board-inner-container"> <div class="list-item">
<div class="media"> <div class="media">
<label class="media-body">{{ title }}</label> <label class="label-light media-body">{{ title }}</label>
<a href="#" @click.prevent="toggleEditing"> <a
v-if="canEdit"
class="edit-link"
href="#"
@click.prevent="toggleEditing"
>
Edit Edit
</a> </a>
</div> </div>
<div class="droplab-dropdown"> <div
<div v-if="editing"> v-if="editing"
<input class="dropdown open"
v-if="fieldName" >
:name="fieldName" <input
> v-if="fieldName"
<slot></slot> :name="fieldName"
</div> >
<div v-else> <slot></slot>
</div>
<div :class="{ invisible: editing }">
<slot name="currentValue">
{{ defaultText }} {{ defaultText }}
</div> </slot>
</div> </div>
</div> </div>
</template> </template>
...@@ -36,6 +44,11 @@ ...@@ -36,6 +44,11 @@
type: String, type: String,
required: false, required: false,
}, },
canEdit: {
type: Boolean,
required: false,
default: false,
}
}, },
data() { data() {
return { return {
......
<template> <template>
<div> <div class="dropdown-menu dropdown-menu-wide">
<gl-dropdown> <div class="dropdown-input">
<template slot="items"> <input
<li class="dropdown-input-field"
v-for="milestone in extraMilestones" type="search"
:key="milestone.id" placeholder="Search milestones">
> <i aria-hidden="true" data-hidden="true" class="fa fa-search dropdown-input-search"></i>
<a </div>
href="#" <ul
@click.prevent.stop="selectMilestone(milestone)"> ref="list"
<i >
class="fa fa-check" <li
v-if="false"></i> v-for="milestone in extraMilestones"
{{ milestone.title }} :key="milestone.id"
</a> >
</li> <a
<li class="divider"></li> href="#"
<li @click.prevent.stop="selectMilestone(milestone)">
v-for="milestone in milestones" <i
:key="milestone.id" class="fa fa-check"
> v-if="false"></i>
<a {{ milestone.title }}
href="#" </a>
@click.prevent.stop="selectMilestone(milestone)"> </li>
<i <li class="divider"></li>
class="fa fa-check" <li v-if="loading">
v-if="false"></i> <loading-icon />
{{ milestone.title }} </li>
</a> <li
</li> v-else
</template> v-for="milestone in milestones"
</gl-dropdown> :key="milestone.id"
>
<a
href="#"
@click.prevent.stop="selectMilestone(milestone)">
<i
class="fa fa-check"
v-if="false"></i>
{{ milestone.title }}
</a>
</li>
</ul>
</div> </div>
</template> </template>
<script> <script>
/* global BoardService */ /* global BoardService */
import DropLab from '~/droplab/drop_lab'; import loadingIcon from '~/vue_shared/components/loading_icon.vue';
import GlDropdown from './dropdown.vue';
import extraMilestones from '../mixins/extra_milestones'; import extraMilestones from '../mixins/extra_milestones';
export default { export default {
...@@ -51,23 +61,29 @@ export default { ...@@ -51,23 +61,29 @@ export default {
type: String, type: String,
required: true, required: true,
}, },
selectMilestone: { value: {
type: Function, type: String,
required: true, required: false,
}, },
}, },
components: {
loadingIcon,
},
data() { data() {
return { return {
loading: false, loading: true,
milestones: [], milestones: [],
extraMilestones, extraMilestones,
}; };
}, },
components: {
GlDropdown,
},
mounted() { mounted() {
BoardService.loadMilestones.call(this); BoardService.loadMilestones.call(this).then(() => this.loading = false);
},
methods: {
selectMilestone(milestone) {
this.board.milestone_id = milestone.id;
this.$emit('input', milestone);
},
}, },
}; };
</script> </script>
...@@ -42,51 +42,58 @@ export default { ...@@ -42,51 +42,58 @@ export default {
</script> </script>
<template> <template>
<div <div class="modal-open">
class="modal popup-dialog"
role="dialog"
tabindex="-1"
>
<div <div
class="modal-dialog modal-lg" class="modal popup-dialog"
role="document" role="dialog"
tabindex="-1"
> >
<div class="modal-content"> <div
<div class="modal-header"> class="modal-dialog modal-md"
<slot name="header"> role="document"
<h4 class="modal-title pull-left">{{this.title}}</h4> >
<button <div class="modal-content">
type="button" <div class="modal-header">
class="close pull-right" <slot name="header">
@click="close" <h4 class="modal-title pull-left">{{this.title}}</h4>
aria-label="Close" <button
> type="button"
<span aria-hidden="true">&times;</span> class="close pull-right"
</button> @click="close"
</slot> aria-label="Close"
</div> >
<div class="modal-body"> <span aria-hidden="true">&times;</span>
<slot> </button>
<p>{{this.body}}</p> </slot>
</div>
<div class="modal-body">
<slot>
<p>{{this.body}}</p>
</slot>
</div>
<slot name="footer">
<div class="modal-footer">
<button type="button"
class="btn pull-left"
:class="btnKindClass"
@click="emitSubmit(true)">
{{primaryButtonLabel}}
</button>
<button
type="button"
class="btn btn-default pull-right"
@click="close">
Cancel
</button>
</div>
</slot> </slot>
</div> </div>
<slot name="footer">
<div class="modal-footer">
<button type="button"
class="btn pull-left"
:class="btnKindClass"
@click="emitSubmit(true)">
{{primaryButtonLabel}}
</button>
<button
type="button"
class="btn btn-default pull-right"
@click="close">
Cancel
</button>
</div>
</slot>
</div> </div>
</div> </div>
<div
class="modal-backdrop fade in"
@click="close"
></div>
</div> </div>
</template> </template>
...@@ -291,6 +291,10 @@ ...@@ -291,6 +291,10 @@
} }
} }
.dropdown-menu-wide {
width: 100%;
}
.droplab-dropdown { .droplab-dropdown {
.dropdown-toggle > i { .dropdown-toggle > i {
pointer-events: none; pointer-events: none;
......
...@@ -390,3 +390,8 @@ ul.indent-list { ...@@ -390,3 +390,8 @@ ul.indent-list {
text-align: center; text-align: center;
} }
} }
.list-item {
padding: $gl-padding 0;
border-bottom: solid 1px $border-color;
}
...@@ -36,6 +36,10 @@ body.modal-open { ...@@ -36,6 +36,10 @@ body.modal-open {
} }
} }
.modal-md {
max-width: 440px;
}
.modal-dialog { .modal-dialog {
// TODO: this needs top and bottom padding (inside content area) // TODO: this needs top and bottom padding (inside content area)
max-height: calc(100vh - #{$new-navbar-height}); max-height: calc(100vh - #{$new-navbar-height});
...@@ -53,12 +57,9 @@ body.modal-open { ...@@ -53,12 +57,9 @@ body.modal-open {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
background-color: $black-transparent;
z-index: 2100;
@media (min-width: $screen-md-min) { @media (min-width: $screen-md-min) {
.modal-dialog { .modal-dialog {
width: 600px;
margin-top: $new-navbar-height; margin-top: $new-navbar-height;
} }
} }
......
...@@ -305,6 +305,10 @@ h6 { ...@@ -305,6 +305,10 @@ h6 {
font-weight: $gl-font-weight-bold; font-weight: $gl-font-weight-bold;
} }
.edit-link {
color: $gl-text-color;
}
.light-header { .light-header {
font-weight: $gl-font-weight-bold; font-weight: $gl-font-weight-bold;
} }
......
...@@ -462,6 +462,10 @@ ...@@ -462,6 +462,10 @@
white-space: normal; white-space: normal;
} }
.form-section-title {
font-size: 16px;
}
.board-delete-btns { .board-delete-btns {
padding-top: 12px; padding-top: 12px;
border-top: 1px solid $border-color; border-top: 1px solid $border-color;
......
...@@ -124,7 +124,7 @@ ...@@ -124,7 +124,7 @@
= icon('times') = icon('times')
.filter-dropdown-container .filter-dropdown-container
- if type == :boards - if type == :boards
.js-board-config .js-board-config{ data: { can_admin_list: can?(current_user, :admin_list, board.parent).to_s } }
- if can?(current_user, :admin_list, board.parent) - if can?(current_user, :admin_list, board.parent)
.dropdown.prepend-left-10#js-add-list .dropdown.prepend-left-10#js-add-list
%button.btn.btn-create.btn-inverted.js-new-board-list{ type: "button", data: board_list_data } %button.btn.btn-create.btn-inverted.js-new-board-list{ type: "button", data: board_list_data }
......
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