Commit 17c576c1 authored by Phil Hughes's avatar Phil Hughes

Removed underscoreJS uses

Removed props on main VueJS app instead uses data variables
parent 4460724d
...@@ -7,7 +7,9 @@ ...@@ -7,7 +7,9 @@
//= require_tree ./mixins //= require_tree ./mixins
//= require_tree ./components //= require_tree ./components
$(function () { $(() => {
const $boardApp = $('#board-app');
if (!window.gl) { if (!window.gl) {
window.gl = {}; window.gl = {};
} }
...@@ -17,38 +19,42 @@ $(function () { ...@@ -17,38 +19,42 @@ $(function () {
} }
gl.IssueBoardsApp = new Vue({ gl.IssueBoardsApp = new Vue({
el: '#board-app', el: $boardApp.get(0),
props: {
disabled: Boolean,
endpoint: String,
issueLinkBase: String
},
data: { data: {
state: BoardsStore.state, state: BoardsStore.state,
loading: true loading: true,
endpoint: $boardApp.data('endpoint'),
disabled: $boardApp.data('disabled'),
issueLinkBase: $boardApp.data('issue-link-base')
}, },
init: function () { init () {
BoardsStore.create(); BoardsStore.create();
}, },
created: function () { created () {
this.loading = true; this.loading = true;
gl.boardService = new BoardService(this.endpoint); gl.boardService = new BoardService(this.endpoint);
$boardApp
.removeAttr('data-endpoint')
.removeAttr('data-disabled')
.removeAttr('data-issue-link-base');
}, },
ready: function () { ready () {
BoardsStore.disabled = this.disabled; BoardsStore.disabled = this.disabled;
gl.boardService.all() gl.boardService.all()
.then((resp) => { .then((resp) => {
const boards = resp.json(); const boards = resp.json();
boards.forEach((board) => { for (let i = 0, boardsLength = boards.length; i < boardsLength; i++) {
const list = BoardsStore.addList(board); const board = boards[i],
list = BoardsStore.addList(board);
if (list.type === 'done') { if (list.type === 'done') {
list.position = 9999999; list.position = Infinity;
} else if (list.type === 'backlog') { } else if (list.type === 'backlog') {
list.position = -1; list.position = -1;
} }
}); }
BoardsStore.addBlankState(); BoardsStore.addBlankState();
this.loading = false; this.loading = false;
......
(function () { (() => {
const Board = Vue.extend({ const Board = Vue.extend({
props: { props: {
list: Object, list: Object,
disabled: Boolean, disabled: Boolean,
issueLinkBase: String issueLinkBase: String
}, },
data: function () { data () {
return { return {
query: '', query: '',
filters: BoardsStore.state.filters filters: BoardsStore.state.filters
}; };
}, },
watch: { watch: {
'query': function () { query () {
if (this.list.canSearch()) { if (this.list.canSearch()) {
this.list.filters = this.getFilterData(); this.list.filters = this.getFilterData();
this.list.getIssues(true); this.list.getIssues(true);
} }
}, },
'filters': { filters: {
handler: function () { handler () {
this.list.page = 1; this.list.page = 1;
this.list.getIssues(true); this.list.getIssues(true);
}, },
...@@ -27,30 +27,33 @@ ...@@ -27,30 +27,33 @@
} }
}, },
methods: { methods: {
clearSearch: function () { clearSearch () {
this.query = ''; this.query = '';
}, },
getFilterData: function () { getFilterData () {
const queryData = this.list.canSearch() ? { search: this.query } : {}; const filters = this.filters;
let queryData = this.list.canSearch() ? { search: this.query } : {};
Object.keys(filters).forEach((key) => { queryData[key] = filters[key]; });
return _.extend(queryData, this.filters); return queryData;
} }
}, },
computed: { computed: {
isPreset: function () { isPreset () {
return this.list.type === 'backlog' || this.list.type === 'done' || this.list.type === 'blank'; return this.list.type === 'backlog' || this.list.type === 'done' || this.list.type === 'blank';
} }
}, },
ready: function () { ready () {
let options = _.extend({ const options = gl.getBoardSortableDefaultOptions({
disabled: this.disabled, disabled: this.disabled,
group: 'boards', group: 'boards',
draggable: '.is-draggable', draggable: '.is-draggable',
handle: '.js-board-handle', handle: '.js-board-handle',
onUpdate: function (e) { onUpdate (e) {
BoardsStore.moveList(e.oldIndex, e.newIndex); BoardsStore.moveList(e.oldIndex, e.newIndex);
} }
}, gl.boardSortableDefaultOptions); });
if (bp.getBreakpointSize() === 'sm' || bp.getBreakpointSize() === 'xs') { if (bp.getBreakpointSize() === 'sm' || bp.getBreakpointSize() === 'xs') {
options.handle = '.js-board-drag-handle'; options.handle = '.js-board-drag-handle';
......
(() => { (() => {
const BoardBlankState = Vue.extend({ const BoardBlankState = Vue.extend({
data: function () { data () {
return { return {
predefinedLabels: [ predefinedLabels: [
new ListLabel({ title: 'Development', color: '#5CB85C' }), new ListLabel({ title: 'Development', color: '#5CB85C' }),
...@@ -11,11 +11,13 @@ ...@@ -11,11 +11,13 @@
} }
}, },
methods: { methods: {
addDefaultLists: function (e) { addDefaultLists (e) {
e.stopImmediatePropagation(); e.stopImmediatePropagation();
BoardsStore.removeBlankState(); BoardsStore.removeBlankState();
_.each(this.predefinedLabels, (label, i) => { for (let i = 0, labelsLength = this.predefinedLabels.length; i < labelsLength; i++) {
const label = this.predefinedLabels[i];
BoardsStore.addList({ BoardsStore.addList({
title: label.title, title: label.title,
position: i, position: i,
...@@ -25,7 +27,7 @@ ...@@ -25,7 +27,7 @@
color: label.color color: label.color
} }
}); });
}); }
// Save the labels // Save the labels
gl.boardService gl.boardService
...@@ -33,15 +35,16 @@ ...@@ -33,15 +35,16 @@
.then((resp) => { .then((resp) => {
const data = resp.json(); const data = resp.json();
_.each(data, (listObj) => { for (let i = 0, dataLength = data.length; i < dataLength; i++) {
const list = BoardsStore.findList('title', listObj.title); const listObj = data[i],
list = BoardsStore.findList('title', listObj.title);
list.id = listObj.id; list.id = listObj.id;
list.label.id = listObj.label.id; list.label.id = listObj.label.id;
list.getIssues(); list.getIssues();
}); }
}); });
}, },
clearBlankState: function () { clearBlankState () {
BoardsStore.removeBlankState(); BoardsStore.removeBlankState();
} }
} }
......
(function () { (() => {
const BoardCard = Vue.extend({ const BoardCard = Vue.extend({
props: { props: {
list: Object, list: Object,
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
disabled: Boolean disabled: Boolean
}, },
methods: { methods: {
filterByLabel: function (label, $event) { filterByLabel (label, $event) {
let labelToggleText = label.title; let labelToggleText = label.title;
const labelIndex = BoardsStore.state.filters['label_name'].indexOf(label.title); const labelIndex = BoardsStore.state.filters['label_name'].indexOf(label.title);
$($event.target).tooltip('hide'); $($event.target).tooltip('hide');
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
list: Object list: Object
}, },
methods: { methods: {
deleteBoard: function (e) { deleteBoard (e) {
e.stopImmediatePropagation(); e.stopImmediatePropagation();
$(this.$el).tooltip('hide'); $(this.$el).tooltip('hide');
......
(function () { (() => {
const BoardList = Vue.extend({ const BoardList = Vue.extend({
props: { props: {
disabled: Boolean, disabled: Boolean,
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
loading: Boolean, loading: Boolean,
issueLinkBase: String issueLinkBase: String
}, },
data: function () { data () {
return { return {
scrollOffset: 250, scrollOffset: 250,
loadingMore: false, loadingMore: false,
...@@ -15,8 +15,8 @@ ...@@ -15,8 +15,8 @@
}; };
}, },
watch: { watch: {
'filters': { filters: {
handler: function () { handler () {
this.loadingMore = false; this.loadingMore = false;
this.$els.list.scrollTop = 0; this.$els.list.scrollTop = 0;
}, },
...@@ -24,16 +24,16 @@ ...@@ -24,16 +24,16 @@
} }
}, },
methods: { methods: {
listHeight: function () { listHeight () {
return this.$els.list.getBoundingClientRect().height; return this.$els.list.getBoundingClientRect().height;
}, },
scrollHeight: function () { scrollHeight () {
return this.$els.list.scrollHeight; return this.$els.list.scrollHeight;
}, },
scrollTop: function () { scrollTop () {
return this.$els.list.scrollTop + this.listHeight(); return this.$els.list.scrollTop + this.listHeight();
}, },
loadNextPage: function () { loadNextPage () {
this.loadingMore = true; this.loadingMore = true;
const getIssues = this.list.nextPage(); const getIssues = this.list.nextPage();
...@@ -44,24 +44,24 @@ ...@@ -44,24 +44,24 @@
} }
}, },
}, },
ready: function () { ready () {
const list = this.list; const list = this.list,
let options = _.extend({ options = gl.getBoardSortableDefaultOptions({
group: 'issues', group: 'issues',
sort: false, sort: false,
disabled: this.disabled, disabled: this.disabled,
onAdd: (e) => { onAdd (e) {
const card = e.item, const card = e.item,
fromListId = parseInt(e.from.getAttribute('data-board')), fromListId = parseInt(e.from.getAttribute('data-board')),
toListId = parseInt(e.to.getAttribute('data-board')), toListId = parseInt(e.to.getAttribute('data-board')),
issueId = parseInt(card.getAttribute('data-issue')); issueId = parseInt(card.getAttribute('data-issue'));
// Remove the new dom element & let vue add the element // Remove the new dom element & let vue add the element
card.parentNode.removeChild(card); card.parentNode.removeChild(card);
BoardsStore.moveCardToList(fromListId, toListId, issueId); BoardsStore.moveCardToList(fromListId, toListId, issueId);
} }
}, gl.boardSortableDefaultOptions); });
if (bp.getBreakpointSize() === 'sm' || bp.getBreakpointSize() === 'xs') { if (bp.getBreakpointSize() === 'sm' || bp.getBreakpointSize() === 'xs') {
options.handle = '.js-card-drag-handle'; options.handle = '.js-card-drag-handle';
......
$(function () { $(() => {
$('.js-new-board-list').each(function () { $('.js-new-board-list').each(function () {
const $this = $(this); const $this = $(this);
new gl.CreateLabelDropdown($this.closest('.dropdown').find('.dropdown-new-label'), $this.data('project-id')); new gl.CreateLabelDropdown($this.closest('.dropdown').find('.dropdown-new-label'), $this.data('project-id'));
$this.glDropdown({ $this.glDropdown({
data: function(term, callback) { data(term, callback) {
$.ajax({ $.ajax({
url: $this.attr('data-labels') url: $this.attr('data-labels')
}).then((resp) => { }).then((resp) => {
callback(resp); callback(resp);
}); });
}, },
renderRow: (label) => { renderRow (label) {
const active = BoardsStore.findList('title', label.title), const active = BoardsStore.findList('title', label.title),
$li = $('<li />',), $li = $('<li />',),
$a = $('<a />', { $a = $('<a />', {
...@@ -32,7 +32,7 @@ $(function () { ...@@ -32,7 +32,7 @@ $(function () {
}, },
filterable: true, filterable: true,
selectable: true, selectable: true,
clicked: (label, $el, e) => { clicked (label, $el, e) {
e.preventDefault(); e.preventDefault();
if (!BoardsStore.findList('title', label.title)) { if (!BoardsStore.findList('title', label.title)) {
......
...@@ -3,19 +3,24 @@ ...@@ -3,19 +3,24 @@
window.gl = {}; window.gl = {};
} }
gl.boardSortableDefaultOptions = { gl.getBoardSortableDefaultOptions = (obj) => {
forceFallback: true, let defaultSortOptions = {
fallbackClass: 'is-dragging', forceFallback: true,
fallbackOnBody: true, fallbackClass: 'is-dragging',
ghostClass: 'is-ghost', fallbackOnBody: true,
filter: '.has-tooltip', ghostClass: 'is-ghost',
scrollSensitivity: 100, filter: '.has-tooltip',
scrollSpeed: 20, scrollSensitivity: 100,
onStart: function () { scrollSpeed: 20,
document.body.classList.add('is-dragging'); onStart () {
}, document.body.classList.add('is-dragging');
onEnd: function () { },
document.body.classList.remove('is-dragging'); onEnd () {
document.body.classList.remove('is-dragging');
}
} }
Object.keys(obj).forEach((key) => { defaultSortOptions[key] = obj[key]; });
return defaultSortOptions;
}; };
})(window); })(window);
...@@ -10,11 +10,12 @@ class ListIssue { ...@@ -10,11 +10,12 @@ class ListIssue {
this.labels = []; this.labels = [];
_.each(obj.labels, (label) => { for (let i = 0, objLabelsLength = obj.labels.length; i < objLabelsLength; i++) {
const label = obj.labels[i];
this.labels.push(new ListLabel(label)); this.labels.push(new ListLabel(label));
}); }
this.priority = _.reduce(this.labels, (max, label) => { this.priority = this.labels.reduce((max, label) => {
return (label.priority < max) ? label.priority : max; return (label.priority < max) ? label.priority : max;
}, Infinity); }, Infinity);
} }
...@@ -30,25 +31,28 @@ class ListIssue { ...@@ -30,25 +31,28 @@ class ListIssue {
} }
findLabel (findLabel) { findLabel (findLabel) {
return _.find(this.labels, (label) => { return this.labels.filter((label) => {
return label.title === findLabel.title; return label.title === findLabel.title;
}); })[0];
} }
removeLabel (removeLabel) { removeLabel (removeLabel) {
if (removeLabel) { if (removeLabel) {
this.labels = _.reject(this.labels, (label) => { this.labels = this.labels.filter((label) => {
return removeLabel.title === label.title; return removeLabel.title !== label.title;
}); });
} }
} }
removeLabels (labels) { removeLabels (labels) {
_.each(labels, this.removeLabel.bind(this)); for (let i = 0, labelsLength = labels.length; i < labelsLength; i++) {
const label = labels[i];
this.removeLabel(label);
}
} }
getLists () { getLists () {
return _.filter(BoardsStore.state.lists, (list) => { return BoardsStore.state.lists.filter((list) => {
return list.findIssue(this.id); return list.findIssue(this.id);
}); });
} }
......
...@@ -33,8 +33,8 @@ class List { ...@@ -33,8 +33,8 @@ class List {
destroy () { destroy () {
if (this.type !== 'blank') { if (this.type !== 'blank') {
BoardsStore.state.lists = _.reject(BoardsStore.state.lists, (list) => { BoardsStore.state.lists = BoardsStore.state.lists.filter((list) => {
return list.id === this.id; return list.id !== this.id;
}); });
BoardsStore.updateNewListDropdown(); BoardsStore.updateNewListDropdown();
...@@ -59,11 +59,14 @@ class List { ...@@ -59,11 +59,14 @@ class List {
} }
getIssues (emptyIssues = true) { getIssues (emptyIssues = true) {
let data = _.extend({ page: this.page }, this.filters); const filters = this.filters;
let data = { page: this.page };
Object.keys(filters).forEach((key) => { data[key] = filters[key]; });
if (this.label) { if (this.label) {
data.label_name = _.reject(data.label_name, (label) => { data.label_name = data.label_name.filter((label) => {
return label === this.label.title; return label !== this.label.title;
}); });
} }
...@@ -85,9 +88,10 @@ class List { ...@@ -85,9 +88,10 @@ class List {
} }
createIssues (data) { createIssues (data) {
_.each(data, (issueObj) => { for (let i = 0, dataLength = data.length; i < dataLength; i++) {
const issueObj = data[i];
this.issues.push(new ListIssue(issueObj)); this.issues.push(new ListIssue(issueObj));
}); }
} }
addIssue (issue, listFrom) { addIssue (issue, listFrom) {
...@@ -99,20 +103,20 @@ class List { ...@@ -99,20 +103,20 @@ class List {
} }
findIssue (id) { findIssue (id) {
return _.find(this.issues, (issue) => { return this.issues.filter((issue) => {
return issue.id === id; return issue.id === id;
}); })[0];
} }
removeIssue (removeIssue) { removeIssue (removeIssue) {
this.issues = _.reject(this.issues, (issue) => { this.issues = this.issues.filter((issue) => {
const matchesRemove = removeIssue.id === issue.id; const matchesRemove = removeIssue.id === issue.id;
if (matchesRemove) { if (matchesRemove) {
issue.removeLabel(this.label); issue.removeLabel(this.label);
} }
return matchesRemove; return !matchesRemove;
}); });
} }
} }
...@@ -55,7 +55,8 @@ class BoardService { ...@@ -55,7 +55,8 @@ class BoardService {
} }
getIssuesForList (id, filter = {}) { getIssuesForList (id, filter = {}) {
const data = _.extend({ id }, filter) let data = { id };
Object.keys(filter).forEach((key) => { data[key] = filter[key]; });
this.setCSRF(); this.setCSRF();
return this.issues.get(data); return this.issues.get(data);
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
w.BoardsStore = { w.BoardsStore = {
disabled: false, disabled: false,
state: {}, state: {},
create: function () { create () {
this.state.lists = []; this.state.lists = [];
this.state.filters = { this.state.filters = {
author_id: gl.utils.getParameterValues('author_id')[0], author_id: gl.utils.getParameterValues('author_id')[0],
...@@ -11,26 +11,29 @@ ...@@ -11,26 +11,29 @@
label_name: gl.utils.getParameterValues('label_name[]') label_name: gl.utils.getParameterValues('label_name[]')
}; };
}, },
addList: function (listObj) { addList (listObj) {
const list = new List(listObj); const list = new List(listObj);
this.state.lists.push(list); this.state.lists.push(list);
return list; return list;
}, },
new: function (listObj) { new (listObj) {
const list = this.addList(listObj), const list = this.addList(listObj),
backlogList = this.findList('type', 'backlog'); backlogList = this.findList('type', 'backlog');
list list
.save() .save()
.then(function () { .then(() => {
// Remove any new issues from the backlog // Remove any new issues from the backlog
// as they will be visible in the new list // as they will be visible in the new list
_.each(list.issues, backlogList.removeIssue.bind(backlogList)); for (let i = 0, issuesLength = list.issues.length; i < issuesLength; i++) {
const issue = list.issues[i];
backlogList.removeIssue(issue);
}
}); });
this.removeBlankState(); this.removeBlankState();
}, },
updateNewListDropdown: function () { updateNewListDropdown () {
const glDropdown = $('.js-new-board-list').data('glDropdown'); const glDropdown = $('.js-new-board-list').data('glDropdown');
if (glDropdown) { if (glDropdown) {
...@@ -41,13 +44,13 @@ ...@@ -41,13 +44,13 @@
} }
} }
}, },
shouldAddBlankState: function () { shouldAddBlankState () {
// Decide whether to add the blank state // Decide whether to add the blank state
return !(!!_.find(this.state.lists, function (list) { return !(this.state.lists.filter((list) => {
return list.type !== 'backlog' && list.type !== 'done'; return list.type !== 'backlog' && list.type !== 'done';
})); })[0]);
}, },
addBlankState: function () { addBlankState () {
if (this.welcomeIsHidden() || this.disabled) return; if (this.welcomeIsHidden() || this.disabled) return;
if (this.shouldAddBlankState()) { if (this.shouldAddBlankState()) {
...@@ -59,26 +62,26 @@ ...@@ -59,26 +62,26 @@
}); });
} }
}, },
removeBlankState: function () { removeBlankState () {
this.removeList('blank'); this.removeList('blank');
$.cookie('issue_board_welcome_hidden', 'true', { $.cookie('issue_board_welcome_hidden', 'true', {
expires: 365 * 10 expires: 365 * 10
}); });
}, },
welcomeIsHidden: function () { welcomeIsHidden () {
return $.cookie('issue_board_welcome_hidden') === 'true'; return $.cookie('issue_board_welcome_hidden') === 'true';
}, },
removeList: function (id) { removeList (id) {
const list = this.findList('id', id); const list = this.findList('id', id);
if (!list) return; if (!list) return;
this.state.lists = _.reject(this.state.lists, (list) => { this.state.lists = this.state.lists.filter((list) => {
return list.id === id; return list.id !== id;
}); });
}, },
moveList: function (oldIndex, newIndex) { moveList (oldIndex, newIndex) {
if (oldIndex === newIndex) return; if (oldIndex === newIndex) return;
const listFrom = this.findList('position', oldIndex), const listFrom = this.findList('position', oldIndex),
...@@ -95,13 +98,13 @@ ...@@ -95,13 +98,13 @@
listFrom.update(); listFrom.update();
}, },
moveCardToList: function (listFromId, listToId, issueId) { moveCardToList (listFromId, listToId, issueId) {
const listFrom = this.findList('id', listFromId), const listFrom = this.findList('id', listFromId),
listTo = this.findList('id', listToId), listTo = this.findList('id', listToId),
issueTo = listTo.findIssue(issueId), issueTo = listTo.findIssue(issueId),
issue = listFrom.findIssue(issueId), issue = listFrom.findIssue(issueId),
issueLists = issue.getLists(), issueLists = issue.getLists(),
listLabels = issueLists.map(function (issue) { listLabels = issueLists.map((issue) => {
return issue.label; return issue.label;
}); });
...@@ -111,20 +114,21 @@ ...@@ -111,20 +114,21 @@
} }
if (listTo.type === 'done' && listFrom.type !== 'backlog') { if (listTo.type === 'done' && listFrom.type !== 'backlog') {
_.each(issueLists, function (list) { for (let i = 0, listsLength = issueLists.length; i < listsLength; i++) {
const list = issueLists[i];
list.removeIssue(issue); list.removeIssue(issue);
}); }
issue.removeLabels(listLabels); issue.removeLabels(listLabels);
} else { } else {
listFrom.removeIssue(issue); listFrom.removeIssue(issue);
} }
}, },
findList: function (key, val) { findList (key, val) {
return _.find(this.state.lists, (list) => { return this.state.lists.filter((list) => {
return list[key] === val; return list[key] === val;
}); })[0];
}, },
updateFiltersUrl: function () { updateFiltersUrl () {
history.pushState(null, null, `?${$.param(this.state.filters)}`); history.pushState(null, null, `?${$.param(this.state.filters)}`);
} }
}; };
......
...@@ -240,7 +240,7 @@ ...@@ -240,7 +240,7 @@
} }
.is-ghost { .is-ghost {
opacity: 0.5; opacity: 0.3;
} }
.is-dragging { .is-dragging {
......
...@@ -11,9 +11,9 @@ ...@@ -11,9 +11,9 @@
= render 'shared/issuable/filter', type: :boards = render 'shared/issuable/filter', type: :boards
.boards-list#board-app{ "v-cloak" => true, .boards-list#board-app{ "v-cloak" => true,
":endpoint" => "'#{namespace_project_board_path(@project.namespace, @project)}'", "data-endpoint" => "#{namespace_project_board_path(@project.namespace, @project)}",
":disabled" => "#{!can?(current_user, :admin_list, @project)}", "data-disabled" => "#{!can?(current_user, :admin_list, @project)}",
":issue-link-base" => "'#{namespace_project_issues_path(@project.namespace, @project)}'" } "data-issue-link-base" => "#{namespace_project_issues_path(@project.namespace, @project)}" }
.boards-app-loading.text-center{ "v-if" => "loading" } .boards-app-loading.text-center{ "v-if" => "loading" }
= icon("spinner spin") = icon("spinner spin")
= render "projects/boards/components/board" = render "projects/boards/components/board"
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