board_form.vue 7.61 KB
Newer Older
Simon Knox's avatar
Simon Knox committed
1
<script>
2
/* global ListLabel */
Simon Knox's avatar
Simon Knox committed
3 4
/* global BoardService */

5
import Flash from '~/flash';
6
import DeprecatedModal from '~/vue_shared/components/deprecated_modal.vue';
7
import BoardLabelsSelect from '~/vue_shared/components/sidebar/labels_select/base.vue';
8
import { visitUrl } from '~/lib/utils/url_utility';
Simon Knox's avatar
Simon Knox committed
9
import BoardMilestoneSelect from './milestone_select.vue';
Simon Knox's avatar
Simon Knox committed
10
import BoardWeightSelect from './weight_select.vue';
Simon Knox's avatar
Simon Knox committed
11
import AssigneeSelect from './assignee_select.vue';
Simon Knox's avatar
Simon Knox committed
12 13 14 15 16

window.gl = window.gl || {};
window.gl.issueBoards = window.gl.issueBoards || {};

const Store = gl.issueBoards.BoardsStore;
17 18 19 20 21 22 23 24 25
const boardDefaults = {
  id: false,
  name: '',
  labels: [],
  milestone_id: undefined,
  assignee: {},
  assignee_id: undefined,
  weight: null,
};
Simon Knox's avatar
Simon Knox committed
26

Simon Knox's avatar
Simon Knox committed
27
export default {
28 29 30 31 32
  components: {
    AssigneeSelect,
    BoardLabelsSelect,
    BoardMilestoneSelect,
    BoardWeightSelect,
33
    DeprecatedModal,
34
  },
Simon Knox's avatar
Simon Knox committed
35
  props: {
Simon Knox's avatar
Simon Knox committed
36 37 38 39 40
    canAdminBoard: {
      type: Boolean,
      required: true,
    },
    milestonePath: {
Simon Knox's avatar
Simon Knox committed
41
      type: String,
42
      required: true,
Simon Knox's avatar
Simon Knox committed
43
    },
Simon Knox's avatar
Simon Knox committed
44 45
    labelsPath: {
      type: String,
46 47
      required: true,
    },
48 49 50 51 52
    scopedIssueBoardFeatureEnabled: {
      type: Boolean,
      required: false,
      default: false,
    },
Simon Knox's avatar
Simon Knox committed
53
    projectId: {
54
      type: Number,
Simon Knox's avatar
Simon Knox committed
55
      required: false,
56
      default: 0,
Simon Knox's avatar
Simon Knox committed
57 58
    },
    groupId: {
59
      type: Number,
Simon Knox's avatar
Simon Knox committed
60
      required: false,
61
      default: 0,
Simon Knox's avatar
Simon Knox committed
62
    },
63 64 65
    weights: {
      type: String,
      required: false,
66
      default: '',
67
    },
Simon Knox's avatar
Simon Knox committed
68 69 70
  },
  data() {
    return {
71
      board: { ...boardDefaults, ...this.currentBoard },
72
      expanded: false,
Simon Knox's avatar
Simon Knox committed
73 74 75 76 77
      issue: {},
      currentBoard: Store.state.currentBoard,
      currentPage: Store.state.currentPage,
      milestones: [],
      milestoneDropdownOpen: false,
78
      isLoading: false,
Simon Knox's avatar
Simon Knox committed
79 80 81
    };
  },
  computed: {
82 83 84 85 86 87 88 89 90
    isNewForm() {
      return this.currentPage === 'new';
    },
    isDeleteForm() {
      return this.currentPage === 'delete';
    },
    isEditForm() {
      return this.currentPage === 'edit';
    },
91 92 93
    isVisible() {
      return this.currentPage !== '';
    },
Simon Knox's avatar
Simon Knox committed
94
    buttonText() {
95
      if (this.isNewForm) {
96
        return 'Create board';
Simon Knox's avatar
Simon Knox committed
97
      }
98
      if (this.isDeleteForm) {
99 100
        return 'Delete';
      }
101
      return 'Save changes';
Simon Knox's avatar
Simon Knox committed
102
    },
103
    buttonKind() {
104 105 106
      if (this.isNewForm) {
        return 'success';
      }
107
      if (this.isDeleteForm) {
108 109 110 111
        return 'danger';
      }
      return 'info';
    },
Simon Knox's avatar
Simon Knox committed
112
    title() {
113
      if (this.isNewForm) {
Simon Knox's avatar
Simon Knox committed
114 115
        return 'Create new board';
      }
116
      if (this.isDeleteForm) {
117 118 119 120 121
        return 'Delete board';
      }
      if (this.readonly) {
        return 'Board scope';
      }
Simon Knox's avatar
Simon Knox committed
122 123
      return 'Edit board';
    },
124
    expandButtonText() {
Simon Knox's avatar
Simon Knox committed
125
      return this.expanded ? 'Collapse' : 'Expand';
126 127
    },
    collapseScope() {
128
      return this.isNewForm;
129 130 131 132
    },
    readonly() {
      return !this.canAdminBoard;
    },
133 134
    weightsArray() {
      return JSON.parse(this.weights);
Simon Knox's avatar
Simon Knox committed
135
    },
136 137 138
    submitDisabled() {
      return this.isLoading || this.board.name.length === 0;
    },
Simon Knox's avatar
Simon Knox committed
139
  },
140 141 142 143 144 145
  mounted() {
    this.resetFormState();
    if (this.$refs.name) {
      this.$refs.name.focus();
    }
  },
Simon Knox's avatar
Simon Knox committed
146
  methods: {
147 148 149 150
    handleLabelClick(label) {
      if (label.isAny) {
        this.board.labels = [];
      } else if (!this.board.labels.find(l => l.id === label.id)) {
151 152 153 154 155 156 157 158
        this.board.labels.push(
          new ListLabel({
            id: label.id,
            title: label.title,
            color: label.color[0],
            textColor: label.text_color,
          }),
        );
159 160 161 162 163 164
      } else {
        let labels = this.board.labels;
        labels = labels.filter(selected => selected.id !== label.id);
        this.board.labels = labels;
      }
    },
Simon Knox's avatar
Simon Knox committed
165
    submit() {
166 167
      if (this.board.name.length === 0) return;
      this.isLoading = true;
168
      if (this.isDeleteForm) {
169 170
        gl.boardService
          .deleteBoard(this.currentBoard)
171
          .then(() => {
Phil Hughes's avatar
Phil Hughes committed
172
            visitUrl(Store.rootPath);
Simon Knox's avatar
Simon Knox committed
173 174
          })
          .catch(() => {
Simon Knox's avatar
Simon Knox committed
175
            Flash('Failed to delete board. Please try again.');
176
            this.isLoading = false;
Simon Knox's avatar
Simon Knox committed
177 178
          });
      } else {
179 180
        gl.boardService
          .createBoard(this.board)
Eric Eastwood's avatar
Eric Eastwood committed
181
          .then(resp => resp.data)
182
          .then(data => {
Phil Hughes's avatar
Phil Hughes committed
183
            visitUrl(data.board_path);
Simon Knox's avatar
Simon Knox committed
184 185
          })
          .catch(() => {
Simon Knox's avatar
Simon Knox committed
186
            Flash('Unable to save your changes. Please try again.');
187
            this.isLoading = false;
Simon Knox's avatar
Simon Knox committed
188 189
          });
      }
Simon Knox's avatar
Simon Knox committed
190 191 192 193
    },
    cancel() {
      Store.state.currentPage = '';
    },
194
    resetFormState() {
Simon Knox's avatar
Simon Knox committed
195
      if (this.isNewForm) {
196
        // Clear the form when we open the "New board" modal
197
        this.board = { ...boardDefaults };
Simon Knox's avatar
Simon Knox committed
198
      } else if (this.currentBoard && Object.keys(this.currentBoard).length) {
199
        this.board = { ...boardDefaults, ...this.currentBoard };
200 201
      }
    },
Simon Knox's avatar
Simon Knox committed
202
  },
Simon Knox's avatar
Simon Knox committed
203
};
Simon Knox's avatar
Simon Knox committed
204
</script>
Simon Knox's avatar
Simon Knox committed
205 206

<template>
207
  <deprecated-modal
208
    v-show="isVisible"
209
    modal-dialog-class="board-config-modal"
Simon Knox's avatar
Simon Knox committed
210
    :hide-footer="readonly"
Simon Knox's avatar
Simon Knox committed
211 212 213 214
    :title="title"
    :primary-button-label="buttonText"
    :kind="buttonKind"
    :submit-disabled="submitDisabled"
215
    @cancel="cancel"
Simon Knox's avatar
Simon Knox committed
216 217
    @submit="submit"
  >
218 219 220 221 222 223 224
    <template slot="body">
      <p v-if="isDeleteForm">
        Are you sure you want to delete this board?
      </p>
      <form
        v-else
        class="js-board-config-modal"
225
        @submit.prevent
Simon Knox's avatar
Simon Knox committed
226 227
      >
        <div
228 229
          v-if="!readonly"
          class="append-bottom-20"
Simon Knox's avatar
Simon Knox committed
230
        >
231 232 233 234 235
          <label
            class="form-section-title label-light"
            for="board-new-name"
          >
            Board name
Simon Knox's avatar
Simon Knox committed
236
          </label>
237 238 239 240 241 242
          <input
            ref="name"
            class="form-control"
            type="text"
            id="board-new-name"
            v-model="board.name"
243
            @keyup.enter="submit"
244
            placeholder="Enter board name"
245
          />
Simon Knox's avatar
Simon Knox committed
246
        </div>
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
        <div v-if="scopedIssueBoardFeatureEnabled">
          <div
            v-if="canAdminBoard"
            class="media append-bottom-10"
          >
            <label class="form-section-title label-light media-body">
              Board scope
            </label>
            <button
              type="button"
              class="btn"
              @click="expanded = !expanded"
              v-if="collapseScope"
            >
              {{ expandButtonText }}
            </button>
          </div>
          <p class="text-secondary append-bottom-10">
            Board scope affects which issues are displayed for anyone who visits this board
          </p>
          <div v-if="!collapseScope || expanded">
            <board-milestone-select
              :board="board"
              :milestone-path="milestonePath"
              :can-edit="canAdminBoard"
            />
Simon Knox's avatar
Simon Knox committed
273

274
            <board-labels-select
275 276
              ability-name="issue"
              :context="board"
277
              :labels-path="labelsPath"
278 279 280 281 282
              :can-edit="canAdminBoard"
              @onLabelClick="handleLabelClick"
            >
              {{ __('Any Label') }}
            </board-labels-select>
Simon Knox's avatar
Simon Knox committed
283

Simon Knox's avatar
Simon Knox committed
284
            <assignee-select
285 286 287 288 289 290 291 292 293 294 295
              any-user-text="Any assignee"
              :board="board"
              field-name="assignee_id"
              label="Assignee"
              :selected="board.assignee"
              :can-edit="canAdminBoard"
              placeholder-text="Select assignee"
              :project-id="projectId"
              :group-id="groupId"
              wrapper-class="assignee"
            />
Simon Knox's avatar
Simon Knox committed
296

297 298 299 300 301 302 303
            <board-weight-select
              :board="board"
              :weights="weightsArray"
              v-model="board.weight"
              :can-edit="canAdminBoard"
            />
          </div>
Simon Knox's avatar
Simon Knox committed
304
        </div>
305 306
      </form>
    </template>
307
  </deprecated-modal>
Simon Knox's avatar
Simon Knox committed
308
</template>