diff --git a/app/assets/javascripts/gitee-frontend/components/boards.js b/app/assets/javascripts/gitee-frontend/components/boards.js index add347982609800869ca4e7e6788b3a77e22d326..7ccb38ad9a30331fee614654397af9346d62b687 100644 --- a/app/assets/javascripts/gitee-frontend/components/boards.js +++ b/app/assets/javascripts/gitee-frontend/components/boards.js @@ -1,1067 +1,1971 @@ /*! - * Gitee-Frontend.js v0.17.1 - * (c) 2019 Liu Chao + * Gitee-Frontend.js v0.22.0 + * (c) 2021 Gitee * Released under the MIT License. */ (function () { - 'use strict'; - - var classCallCheck = function (instance, Constructor) { - if (!(instance instanceof Constructor)) { - throw new TypeError("Cannot call a class as a function"); - } - }; - - var createClass = function () { - function defineProperties(target, props) { - for (var i = 0; i < props.length; i++) { - var descriptor = props[i]; - descriptor.enumerable = descriptor.enumerable || false; - descriptor.configurable = true; - if ("value" in descriptor) descriptor.writable = true; - Object.defineProperty(target, descriptor.key, descriptor); - } - } - - return function (Constructor, protoProps, staticProps) { - if (protoProps) defineProperties(Constructor.prototype, protoProps); - if (staticProps) defineProperties(Constructor, staticProps); - return Constructor; - }; - }(); - - var inherits = function (subClass, superClass) { - if (typeof superClass !== "function" && superClass !== null) { - throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); - } - - subClass.prototype = Object.create(superClass && superClass.prototype, { - constructor: { - value: subClass, - enumerable: false, - writable: true, - configurable: true - } - }); - if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; - }; - - var possibleConstructorReturn = function (self, call) { - if (!self) { - throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); - } - - return call && (typeof call === "object" || typeof call === "function") ? call : self; - }; - - var defaults$1 = { - readonly: false, - key: 'state', - name: 'board', - message: { - loading: 'loading ...', - stateDisabled: 'Current issue cannot switch to this state', - allComplete: 'Showing all issues', - empty: 'There are no issues here', - btnSetFirst: 'Move it to the first', - btnSetLast: 'Move it to the last' - }, - className: { - iconComment: 'icon comments outline', - iconAngleLeft: 'icon angle double left', - iconAngleRight: 'icon angle double right', - iconIssue: 'icon sticky note outline', - card: 'ui link card', - action: 'ui button', - actions: 'ui mini basic icon buttons', - avatar: 'ui avatar image' - }, - actions: function actions(config) { - if (!config.plugins.Sortable) { - return []; - } - return [{ - id: 'btn-set-first', - class: config.className.action, - icon: config.className.iconAngleLeft, - title: config.message.btnSetFirst, - callback: function callback(boards, board) { - var state = board.state.toString(); - var states = boards.sortable.toArray(); - var i = states.indexOf(state); - - if (i >= 0) { - states.splice(i, 1); - states.splice(0, 0, state); - boards.sortable.sort(states); - config.onSorted(states); - boards.load(); - } - } - }, { - id: 'btn-set-last', - class: config.className.action, - icon: config.className.iconAngleRight, - title: config.message.btnSetLast, - callback: function callback(boards, board) { - var state = board.state.toString(); - var states = boards.sortable.toArray(); - var i = states.indexOf(state); - - if (i >= 0) { - states.splice(i, 1); - states.push(state); - boards.sortable.sort(states); - config.onSorted(states); - boards.load(); - } - } - }]; - }, - - data: [{ - order: 1, - name: 'Backlog', - state: 'open', - color: '#ffa726', - issuesCount: 0 - }, { - order: 2, - name: 'Done', - state: 'closed', - color: '#2baf2b', - issuesCount: 0 - }], - plugins: {}, - types: [], - user: { - id: 0, - admin: false - }, - - /** - * 在任务列表加载完后的回调 - * @callback BoardLoadCallback - * @param {Array} issues 任务列表 - * @param {Number} count 任务总数 - */ - - /** - * 在开始加载任务列表时的回调 - * @param {Object,Board} board 板块对象 - * @param {BoardLoadCallback} callback 用于接收任务列表的回调函数 - */ - onLoad: function onLoad(board, callback) { - $.ajax({ - url: 'issues', - data: { - state: board.state, - page: board.page - } - }).done(function () { - callback([], 0); - }).fail(function () { - callback([], 0); - }); - }, - - /** - * 在更新任务时的回调 - * @param {Object} issue 任务 - * @param {String,Number} oldState 更新前的状态 - */ - onUpdate: function onUpdate(issue, oldState) { - var _this = this; - - $.ajax({ - type: 'PUT', - url: issue.url, - data: { - state: issue.state - } - }).done(function (res) { - _this.updateIssue(res); - }).fail(function () { - _this.setIssueState(issue.id, oldState); - }); - }, - - /** - * 在渲染任务卡片时的回调 - * @param {Object} issue 任务 - * @param {JQuery} $el 任务卡片 - */ - onRender: function onRender(issue, $el) { - $el.addClass('issue-state-' + issue.state); - return $el; - }, - - /** - * 在板块被排序后的回调 - * @param {Array} states 状态列表 - */ - onSorted: function onSorted(states) { - window.console.log(states); - } - }; - - var Config = function Config(config) { - classCallCheck(this, Config); - - $.extend(this, defaults$1, config); - if (config.className) { - this.className = $.extend({}, defaults$1.className, config.className); - } - if (config.message) { - this.message = $.extend({}, defaults$1.message, config.message); - } - }; - - var htmlSafe = function () { - var $el = $('
'); - - return function (text) { - return $el.text(text).html(); - }; - }(); - - var Renderer = function () { - function Renderer(config) { - classCallCheck(this, Renderer); - - this.config = config; - } - - createClass(Renderer, [{ - key: 'getAvatarUrl', - value: function getAvatarUrl(name, avatarUrl) { - var Avatar = this.config.plugins.LetterAvatar; - if (!avatarUrl || avatarUrl.indexOf('no_portrait.png') === 0) { - if (Avatar) { - return Avatar(name); - } - } - return avatarUrl; - } - }, { - key: 'getCardId', - value: function getCardId(issue) { - if (this.config.getIusseId) { - return this.config.getIusseId(issue); - } - return 'issue-card-' + issue.id; - } - }]); - return Renderer; - }(); - - /* eslint-disable indent */ - - function getUserUrl(user) { - return user.html_url || user.path; - } - - function renderCardUserLabel(issue) { - if (!issue.author) { - return ''; - } - if (typeof issue.author.is_member !== 'undefined') { - if (!issue.author.is_member) { - return '[访客]'; - } - } - if (issue.author.outsourced) { - return '[外包]'; - } - return ''; - } - - function renderCardLabels(issue) { - var html = ''; - - if (!issue.labels) { - return ''; - } - - issue.labels.forEach(function (label) { - html += ['', htmlSafe(label.name), ''].join(''); - }); - return '
' + html + '
'; - } - - var CardRenderer = function (_Renderer) { - inherits(CardRenderer, _Renderer); - - function CardRenderer() { - classCallCheck(this, CardRenderer); - return possibleConstructorReturn(this, (CardRenderer.__proto__ || Object.getPrototypeOf(CardRenderer)).apply(this, arguments)); - } - - createClass(CardRenderer, [{ - key: 'render', - value: function render$$1(issue) { - var user = this.config.user; - var readonly = this.config.readonly; - - var draggable = ''; - var cardClass = this.config.className.card; - - if (!readonly && (user.admin || user.id === issue.author.id)) { - draggable = 'draggable="true"'; - cardClass += ' card-draggable'; - } - return ['
  • ', '', '
    ', this.renderAssignee(issue), this.renderState(issue), '#', issue.number, '', 'by ', htmlSafe(issue.author.name), '', renderCardUserLabel(issue), this.renderComments(issue), renderCardLabels(issue), '
    ', '
  • '].join(''); - } - }, { - key: 'renderState', - value: function renderState(issue) { - var state = issue.state_data; - - if (!state || this.config.key === 'state') { - return ''; - } - return ['
    ', '', '
    '].join(''); - } - }, { - key: 'renderAssignee', - value: function renderAssignee(issue) { - var user = issue.assignee; - - if (!user || !user.id || this.config.key !== 'state') { - return ''; - } - return ['
    ', '', '', htmlSafe(user.name), '', '', '
    '].join(''); - } - }, { - key: 'renderComments', - value: function renderComments(issue) { - var className = this.config.className.iconComment; - - if (!issue.comments) { - return ''; - } - return '' + (issue.comments + ''); - } - }]); - return CardRenderer; - }(Renderer); - - /* eslint-disable no-plusplus */ - - function setColorAlpha(color, alpha) { - var reg = /^#([\da-fA-F]{2})([\da-fA-F]{2})([\da-fA-F]{2})$/; - var matches = reg.exec(color); - var r = parseInt(matches[1], 16); - var g = parseInt(matches[2], 16); - var b = parseInt(matches[3], 16); - return 'rgba(' + r + ',' + g + ',' + b + ',' + alpha + ')'; - } - - function renderBoardIcon(board) { - var iconStyle = ''; - - if (board.color) { - iconStyle = 'style="color: ' + board.color + '"'; - } - if (board.icon) { - return ''; - } - return ''; - } - - var BoardRenderer = function (_Renderer) { - inherits(BoardRenderer, _Renderer); - - function BoardRenderer() { - classCallCheck(this, BoardRenderer); - return possibleConstructorReturn(this, (BoardRenderer.__proto__ || Object.getPrototypeOf(BoardRenderer)).apply(this, arguments)); - } - - createClass(BoardRenderer, [{ - key: 'render', - value: function render$$1(board) { - return ['
    ', '
    ', this.renderHeader(board), '
    ', '
      ', '
      ', '
      ', '
      ', '
      ', '

      ', '

      ', this.config.message.stateDisabled, '

      ', '
      ', '
      ', '
      ', '
      '].join(''); - } - }, { - key: 'renderHeader', - value: function renderHeader(board) { - var headerStyle = ''; - var headerClass = 'board-header'; - - if (board.color) { - if (board.colorTarget === 'background') { - headerStyle = 'background-color: ' + setColorAlpha(board.color, 0.04); - } else { - headerClass += ' has-border'; - headerStyle = 'border-color: ' + board.color; - } - } - return ['
      ', '

      ', this.renderActions(), '
      ', '', '', board.issuesCount, '', '
      ', this.renderAvatar(board), renderBoardIcon(board), htmlSafe(board.name), '

      ', '
      '].join(''); - } - }, { - key: 'renderActions', - value: function renderActions() { - var config = this.config; - var actions = config.actions; - - if (typeof actions === 'function') { - actions = actions(config); - } - return ['
      ', actions.map(function (a) { - return [''].join(''); - }).join(''), '
      '].join(''); - } - }, { - key: 'renderAvatar', - value: function renderAvatar(board) { - if (!board.avatarUrl) { - return ''; - } - return ['', board.state, ''].join(''); - } - }, { - key: 'renderTip', - value: function renderTip(board) { - var msg = this.config.message; - - if (board.loadable) { - return ['
    • ', ' ', msg.loading, '
    • '].join(''); - } - if (board.completed && board.issues.length > 0) { - return ['
    • ', msg.allComplete, '
    • '].join(''); - } - return ['
    • ', msg.empty, '
    • '].join(''); - } - }]); - return BoardRenderer; - }(Renderer); - - var Board = function () { - function Board(data, config) { - var _this2 = this; - - classCallCheck(this, Board); - - this.page = 0; - this.loadable = true; - this.loading = false; - this.completed = false; - this.issues = []; - - this.name = data.name; - this.icon = data.icon; - this.state = data.state; - this.color = data.color; - this.colorTarget = data.colorTarget; - this.issuesCount = data.issuesCount || 0; - this.avatarUrl = data.avatarUrl; - - this.config = config; - - this.renderer = new BoardRenderer(config); - this.cardRenderer = new CardRenderer(config); - - this.$tip = null; - this.$el = $(this.renderer.render(this)); - this.$dimmer = this.$el.find('.ui.dimmer'); - this.$issues = this.$el.find('.board-list'); - this.$issuesCount = this.$el.find('.issues-count'); - - this.$issues.on('scroll', function () { - _this2.autoload(); - }); - } - - createClass(Board, [{ - key: 'add', - value: function add(issue) { - this.issues.push(issue); - this.issuesCount += 1; - this.$issuesCount.text(this.issuesCount); - } - }, { - key: 'find', - value: function find(id) { - for (var i = 0; i < this.issues.length; ++i) { - var issue = this.issues[i]; - if (issue.id === id) { - return i; - } - } - return -1; - } - }, { - key: 'get', - value: function get$$1(id) { - var i = this.find(id); - - if (i >= 0) { - return this.issues[i]; - } - return null; - } - }, { - key: 'remove', - value: function remove(id) { - var i = this.find(id); - - if (i >= 0) { - this.issuesCount -= 1; - this.$issuesCount.text(this.issuesCount); - return this.issues.splice(i, 1); - } - return null; - } - }, { - key: 'clear', - value: function clear() { - this.page = 0; - this.issues = []; - this.issuesCount = 0; - this.loading = false; - this.loadable = true; - this.completed = false; - - this.$issuesCount.text(0); - this.$issues.empty(); - this.$tip = null; - } - }, { - key: 'autoload', - value: function autoload() { - if (this.completed) { - return; - } - if (!this.$tip || this.$tip.position().top < this.$issues.height()) { - this.load(); - } - } - }, { - key: 'load', - value: function load() { - if (this.loading) { - return false; - } - this.page += 1; - this.loading = true; - if (this.page === 1) { - this.$dimmer.addClass('active'); - } - this.config.onLoad(this, this.onLoadDone.bind(this)); - return true; - } - }, { - key: 'onLoadDone', - value: function onLoadDone(issues, count) { - this.issuesCount = count; - this.$issuesCount.text(this.issuesCount); - this.appendIssues(issues); - if (this.issuesCount > 0) { - if (issues.length < 1 || this.issuesCount === issues.length) { - this.loadable = false; - this.completed = true; - } else { - this.loadable = true; - this.completed = false; - } - } else { - this.loadable = false; - this.completed = true; - } - if (this.page === 1) { - this.$dimmer.removeClass('active'); - } - this.loading = false; - this.updateTip(); - this.autoload(); - } - - /* 进行初次加载 */ - - }, { - key: 'firstload', - value: function firstload() { - if (this.page > 0) { - return false; - } - return this.load(); - } - - /** - * 更新提示 - */ - - }, { - key: 'updateTip', - value: function updateTip() { - if (this.$tip) { - this.$tip.remove(); - } - this.$tip = $(this.renderer.renderTip(this)); - this.$issues.append(this.$tip); - } - }, { - key: 'createCard', - value: function createCard(issue) { - var $card = $(this.cardRenderer.render(issue)); - var onSelect = this.config.onSelect; - - if (onSelect) { - $card.on('click', function (e) { - var $target = $(e.target); - - if (!$target.is('a')) { - $target = $target.parent(); - } - if (!$target.parent().hasClass('card-header') && $target.is('a') && $target.attr('href')) { - return; - } - onSelect(issue, e); - }); - } - return this.config.onRender(issue, $card, this.config); - } - }, { - key: 'appendIssue', - value: function appendIssue(issue) { - this.issues.push(issue); - this.$issues.append(this.createCard(issue)); - } - }, { - key: 'prependIssue', - value: function prependIssue(issue) { - this.issuesCount += 1; - this.issues.splice(0, 0, issue); - this.$issues.prepend(this.createCard(issue)); - this.$issuesCount.text(this.issuesCount); - } - }, { - key: 'updateIssue', - value: function updateIssue(issue) { - var $issue = $('#' + this.config.name + '-issue-' + issue.id); - - if ($issue.length < 1) { - this.prependIssue(issue); - return; - } - $issue.before(this.createCard(issue)).remove(); - } - - /** - * 直接追加多个任务,不更新任务总数 - * @param {Array} issues 任务列表 - */ - - }, { - key: 'appendIssues', - value: function appendIssues(issues) { - var _this3 = this; - - issues.filter(function (issue) { - return _this3.issues.every(function (boardIssue) { - return boardIssue.id !== issue.id; - }); - }).forEach(function (issue) { - issue[_this3.config.Key] = _this3.state; - _this3.appendIssue(issue); - }); - } - }]); - return Board; - }(); - - var Boards = function () { - /** - * 创建一个看板 - * @param {JQuery} $el 看板容器元素 - * @param {BoardsSettings} options 配置 - */ - function Boards($el, options) { - classCallCheck(this, Boards); - - var config = new Config(options); - - this.$el = $el; - this.config = config; - - this.boards = {}; - this.$hoverIssue = null; - this.$selectedIssue = null; - this.timerForScrollLoad = null; - - this.bindDrag(); - this.bindScroll(); - this.initPlugins(); - this.setData(config.data); - } - - createClass(Boards, [{ - key: 'initPlugins', - value: function initPlugins() { - this.initSortable(); - } - - // 初始化拖拽排序功能 - - }, { - key: 'initSortable', - value: function initSortable() { - var that = this; - var Sortable = that.config.plugins.Sortable; - - // 如果没有注入 SortableJS 依赖,则不启用这个功能 - if (!Sortable) { - return false; - } - that.$el.addClass('boards-sortable'); - that.sortable = Sortable.create(that.$el[0], { - handle: '.board-title', - dataIdAttr: 'data-state', - onUpdate: function onUpdate() { - that.config.onSorted(that.sortable.toArray()); - } - }); - that.$el.on('click', '.board-action', function (e) { - var $target = $(this); - var id = $target.data('id'); - var state = $target.parents('.board').data('state'); - var actions = that.config.actions; - - if (typeof actions === 'function') { - actions = actions(that.config); - } - actions.some(function (action) { - if (action.id === id && action.callback) { - action.callback(that, that.boards[state], e); - return true; - } - return false; - }); - }); - return true; - } - }, { - key: 'bindScroll', - value: function bindScroll() { - var that = this; - var timerForScrollLoad = null; - - function onScrollLoad() { - if (timerForScrollLoad) { - clearTimeout(timerForScrollLoad); - } - timerForScrollLoad = setTimeout(function () { - timerForScrollLoad = null; - that.load(); - }, 200); - } - - $(window).on('resize', onScrollLoad); - this.$el.on('scroll', onScrollLoad); - } - }, { - key: 'bindDrag', - value: function bindDrag() { - var that = this; - - if (that.config.readonly) { - return; - } - that.$el.on('dragstart', '.card', function (e) { - var issueId = $(this).data('id'); - var issue = that.getIssue(issueId); - - if (issue) { - that.setFocus(issue.type, issue.state); - } - that.$selectedIssue = $(this); - e.originalEvent.dataTransfer.setData('text/plain', issueId); - e.stopPropagation(); - }); - that.$el.on('dragend', '.card', function () { - that.clearFocus(); - }); - that.$el.on('drop', '.board-list', function (e) { - e.preventDefault(); - e.stopPropagation(); - - if (that.$hoverIssue) { - that.$hoverIssue.removeClass('card-dragover'); - } - if (!that.$selectedIssue) { - return false; - } - if (that.config.readonly) { - return false; - } - - var $issue = that.$selectedIssue; - var issueId = $issue.data('id'); - var $board = $(this).parents('.board'); - var state = $board.data('state'); - var oldState = $issue.parents('.board').data('state'); - var nextIssueId = that.$hoverIssue ? that.$hoverIssue.data('id') : null; - - that.setIssueState(issueId, state, nextIssueId, function (issue) { - that.config.onUpdate(issue, oldState, nextIssueId); - }); - return true; - }); - that.$el.on('dragover', '.board-list', function (e) { - var key = that.config.key; - var $target = $(e.target); - - if (!that.$selectedIssue) { - return; - } - - e.preventDefault(); - while ($target.length > 0 && !$target.hasClass('card')) { - $target = $target.parent(); - } - if ($target.length < 1) { - if (that.$hoverIssue) { - that.$hoverIssue.removeClass('card-dragover'); - } - that.$hoverIssue = null; - return; - } - if (that.$hoverIssue) { - that.$hoverIssue.removeClass('card-dragover'); - } - that.$hoverIssue = $target; - var hoverIssue = that.getIssue($target.data('id')); - var selectedIssue = that.getIssue(that.$selectedIssue.data('id')); - if (hoverIssue && selectedIssue && hoverIssue[key] !== selectedIssue[key]) { - that.$hoverIssue.addClass('card-dragover'); - } - }); - } - - /** - * 设置焦点板块 - * 根据指定的类型和状态,排除无关状态的板块 - * @param {String, Number} typeId 任务类型 id - * @param {String, Number} stateId 任务状态 id - */ - - }, { - key: 'setFocus', - value: function setFocus(typeId, stateId) { - var _this = this; - - var stateIds = []; - var issueType = null; - - if (this.config.key !== 'state') { - return; - } - this.config.types.some(function (t) { - if (t.id === typeId) { - issueType = t; - return true; - } - return false; - }); - if (issueType) { - stateIds = issueType.states.map(function (state) { - return state.id.toString(); - }); - } - Object.keys(this.boards).forEach(function (id) { - if (id !== stateId.toString() && stateIds.indexOf(id) === -1) { - _this.boards[id].$el.addClass('board-blur'); - } - }); - } - - /* 清除板块的焦点效果 */ - - }, { - key: 'clearFocus', - value: function clearFocus() { - var _this2 = this; - - Object.keys(this.boards).forEach(function (key) { - _this2.boards[key].$el.removeClass('board-blur'); - }); - } - }, { - key: 'getIssueCard', - value: function getIssueCard(id) { - return $('#' + this.config.name + '-issue-' + id); - } - }, { - key: 'getIssue', - value: function getIssue(id) { - var $issue = this.getIssueCard(id); - var $board = $issue.parents('.board'); - var state = $board.data('state'); - var board$$1 = this.boards[state]; - if (board$$1) { - return board$$1.get(id); - } - return null; - } - }, { - key: 'removeIssue', - value: function removeIssue(id) { - var issue = null; - var $issue = this.getIssueCard(id); - - if ($issue.length < 1) { - return issue; - } - - var state = $issue.parents('.board').data('state'); - if (state) { - var board$$1 = this.boards[state]; - if (board$$1) { - issue = board$$1.remove(id); - } - } - - $issue.remove(); - return issue; - } - }, { - key: 'updateIssue', - value: function updateIssue(issue) { - var board$$1 = this.boards[issue[this.config.key]]; - - if (board$$1) { - board$$1.updateIssue(issue); - return true; - } - return false; - } - }, { - key: 'prependIssue', - value: function prependIssue(issue) { - var board$$1 = this.boards[issue[this.config.key]]; - - if (board$$1) { - board$$1.prependIssue(issue); - return true; - } - return false; - } - }, { - key: 'setIssueState', - value: function setIssueState(issueId, state, nextIssueId, callback) { - var $issue = this.getIssueCard(issueId); - var $nextIssue = nextIssueId ? this.getIssueCard(nextIssueId) : null; - - if ($issue.length < 1) { - return null; - } - - var user = this.config.user; - var $oldBoard = $issue.parents('.board'); - var oldState = $oldBoard.data('state'); - var oldBoard = this.boards[oldState]; - var newBoard = this.boards[state]; - - if (oldBoard.state === state) { - return null; - } - - // 如果新的板块不接受该状态的 issue - if (newBoard.exclude && newBoard.exclude.indexOf(oldState) >= 0) { - return null; - } - - var issue = oldBoard.get(issueId); - // 如果当前用户既不具备管理权限,也不是 issue 作者,则禁止操作 - if (!user.admin && issue.author.id !== user.id) { - return null; - } - - issue[this.config.key] = state; - newBoard.add(issue); - oldBoard.remove(issue.id); - $issue.hide(256, function () { - // 如果有指定下一个 issue,则将当前 issue 插入到它前面 - if ($nextIssue) { - $nextIssue.before($issue); - } else { - newBoard.$issues.prepend($issue); - } - $issue.show(256, function () { - if (callback) { - callback(issue); - } - }); - }); - newBoard.updateTip(); - oldBoard.updateTip(); - oldBoard.autoload(); - - return issue; - } - }, { - key: 'load', - value: function load() { - var _this3 = this; - - var count = 0; - var bound = this.$el.offset(); - - // 设置边界框(可见区域)的尺寸 - bound.width = this.$el.width(); - bound.height = this.$el.height(); - - Object.keys(this.boards).forEach(function (state) { - var board$$1 = _this3.boards[state]; - var offset = board$$1.$el.offset(); - // 如果当前板块在可见区域内 - if (offset.top + board$$1.$el.height() > bound.top && offset.left + board$$1.$el.width() > bound.left && offset.top < bound.top + bound.height && offset.left < bound.left + bound.width) { - if (board$$1.firstload()) { - count += 1; - } - } - }); - return count; - } - }, { - key: 'setData', - value: function setData(data) { - var _this4 = this; - - this.boards = {}; - this.$el.addClass('boards-list').empty(); - - data.forEach(function (boardData) { - var board$$1 = new Board(boardData, _this4.config); - _this4.boards[boardData.state] = board$$1; - _this4.$el.append(board$$1.$el); - }); - } - }, { - key: 'clearData', - value: function clearData() { - var _this5 = this; - - Object.keys(this.boards).forEach(function (state) { - _this5.boards[state].clear(); - }); - } - }]); - return Boards; - }(); - - $.fn.boards = function (options) { - var that = this.data('boards'); - var settings = $.extend({}, $.fn.boards.settings, options); - - if (!that) { - that = new Boards(this, settings); - this.data('boards', that); - that.load(); - } - return this; - }; - - $.fn.boards.settings = defaults$1; + 'use strict'; + + function unwrapExports (x) { + return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; + } + + function createCommonjsModule(fn, module) { + return module = { exports: {} }, fn(module, module.exports), module.exports; + } + + var classCallCheck = createCommonjsModule(function (module) { + function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + } + + module.exports = _classCallCheck; + module.exports["default"] = module.exports, module.exports.__esModule = true; + }); + var _classCallCheck = unwrapExports(classCallCheck); + + var createClass = createCommonjsModule(function (module) { + function _defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + + function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + return Constructor; + } + + module.exports = _createClass; + module.exports["default"] = module.exports, module.exports.__esModule = true; + }); + var _createClass = unwrapExports(createClass); + + var runtime_1 = createCommonjsModule(function (module) { + /** + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + var runtime = function (exports) { + + var Op = Object.prototype; + var hasOwn = Op.hasOwnProperty; + var undefined$1; // More compressible than void 0. + + var $Symbol = typeof Symbol === "function" ? Symbol : {}; + var iteratorSymbol = $Symbol.iterator || "@@iterator"; + var asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator"; + var toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag"; + + function define(obj, key, value) { + Object.defineProperty(obj, key, { + value: value, + enumerable: true, + configurable: true, + writable: true + }); + return obj[key]; + } + + try { + // IE 8 has a broken Object.defineProperty that only works on DOM objects. + define({}, ""); + } catch (err) { + define = function (obj, key, value) { + return obj[key] = value; + }; + } + + function wrap(innerFn, outerFn, self, tryLocsList) { + // If outerFn provided and outerFn.prototype is a Generator, then outerFn.prototype instanceof Generator. + var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator; + var generator = Object.create(protoGenerator.prototype); + var context = new Context(tryLocsList || []); // The ._invoke method unifies the implementations of the .next, + // .throw, and .return methods. + + generator._invoke = makeInvokeMethod(innerFn, self, context); + return generator; + } + + exports.wrap = wrap; // Try/catch helper to minimize deoptimizations. Returns a completion + // record like context.tryEntries[i].completion. This interface could + // have been (and was previously) designed to take a closure to be + // invoked without arguments, but in all the cases we care about we + // already have an existing method we want to call, so there's no need + // to create a new function object. We can even get away with assuming + // the method takes exactly one argument, since that happens to be true + // in every case, so we don't have to touch the arguments object. The + // only additional allocation required is the completion record, which + // has a stable shape and so hopefully should be cheap to allocate. + + function tryCatch(fn, obj, arg) { + try { + return { + type: "normal", + arg: fn.call(obj, arg) + }; + } catch (err) { + return { + type: "throw", + arg: err + }; + } + } + + var GenStateSuspendedStart = "suspendedStart"; + var GenStateSuspendedYield = "suspendedYield"; + var GenStateExecuting = "executing"; + var GenStateCompleted = "completed"; // Returning this object from the innerFn has the same effect as + // breaking out of the dispatch switch statement. + + var ContinueSentinel = {}; // Dummy constructor functions that we use as the .constructor and + // .constructor.prototype properties for functions that return Generator + // objects. For full spec compliance, you may wish to configure your + // minifier not to mangle the names of these two functions. + + function Generator() {} + + function GeneratorFunction() {} + + function GeneratorFunctionPrototype() {} // This is a polyfill for %IteratorPrototype% for environments that + // don't natively support it. + + + var IteratorPrototype = {}; + + IteratorPrototype[iteratorSymbol] = function () { + return this; + }; + + var getProto = Object.getPrototypeOf; + var NativeIteratorPrototype = getProto && getProto(getProto(values([]))); + + if (NativeIteratorPrototype && NativeIteratorPrototype !== Op && hasOwn.call(NativeIteratorPrototype, iteratorSymbol)) { + // This environment has a native %IteratorPrototype%; use it instead + // of the polyfill. + IteratorPrototype = NativeIteratorPrototype; + } + + var Gp = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(IteratorPrototype); + GeneratorFunction.prototype = Gp.constructor = GeneratorFunctionPrototype; + GeneratorFunctionPrototype.constructor = GeneratorFunction; + GeneratorFunction.displayName = define(GeneratorFunctionPrototype, toStringTagSymbol, "GeneratorFunction"); // Helper for defining the .next, .throw, and .return methods of the + // Iterator interface in terms of a single ._invoke method. + + function defineIteratorMethods(prototype) { + ["next", "throw", "return"].forEach(function (method) { + define(prototype, method, function (arg) { + return this._invoke(method, arg); + }); + }); + } + + exports.isGeneratorFunction = function (genFun) { + var ctor = typeof genFun === "function" && genFun.constructor; + return ctor ? ctor === GeneratorFunction || // For the native GeneratorFunction constructor, the best we can + // do is to check its .name property. + (ctor.displayName || ctor.name) === "GeneratorFunction" : false; + }; + + exports.mark = function (genFun) { + if (Object.setPrototypeOf) { + Object.setPrototypeOf(genFun, GeneratorFunctionPrototype); + } else { + genFun.__proto__ = GeneratorFunctionPrototype; + define(genFun, toStringTagSymbol, "GeneratorFunction"); + } + + genFun.prototype = Object.create(Gp); + return genFun; + }; // Within the body of any async function, `await x` is transformed to + // `yield regeneratorRuntime.awrap(x)`, so that the runtime can test + // `hasOwn.call(value, "__await")` to determine if the yielded value is + // meant to be awaited. + + + exports.awrap = function (arg) { + return { + __await: arg + }; + }; + + function AsyncIterator(generator, PromiseImpl) { + function invoke(method, arg, resolve, reject) { + var record = tryCatch(generator[method], generator, arg); + + if (record.type === "throw") { + reject(record.arg); + } else { + var result = record.arg; + var value = result.value; + + if (value && typeof value === "object" && hasOwn.call(value, "__await")) { + return PromiseImpl.resolve(value.__await).then(function (value) { + invoke("next", value, resolve, reject); + }, function (err) { + invoke("throw", err, resolve, reject); + }); + } + + return PromiseImpl.resolve(value).then(function (unwrapped) { + // When a yielded Promise is resolved, its final value becomes + // the .value of the Promise<{value,done}> result for the + // current iteration. + result.value = unwrapped; + resolve(result); + }, function (error) { + // If a rejected Promise was yielded, throw the rejection back + // into the async generator function so it can be handled there. + return invoke("throw", error, resolve, reject); + }); + } + } + + var previousPromise; + + function enqueue(method, arg) { + function callInvokeWithMethodAndArg() { + return new PromiseImpl(function (resolve, reject) { + invoke(method, arg, resolve, reject); + }); + } + + return previousPromise = // If enqueue has been called before, then we want to wait until + // all previous Promises have been resolved before calling invoke, + // so that results are always delivered in the correct order. If + // enqueue has not been called before, then it is important to + // call invoke immediately, without waiting on a callback to fire, + // so that the async generator function has the opportunity to do + // any necessary setup in a predictable way. This predictability + // is why the Promise constructor synchronously invokes its + // executor callback, and why async functions synchronously + // execute code before the first await. Since we implement simple + // async functions in terms of async generators, it is especially + // important to get this right, even though it requires care. + previousPromise ? previousPromise.then(callInvokeWithMethodAndArg, // Avoid propagating failures to Promises returned by later + // invocations of the iterator. + callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); + } // Define the unified helper method that is used to implement .next, + // .throw, and .return (see defineIteratorMethods). + + + this._invoke = enqueue; + } + + defineIteratorMethods(AsyncIterator.prototype); + + AsyncIterator.prototype[asyncIteratorSymbol] = function () { + return this; + }; + + exports.AsyncIterator = AsyncIterator; // Note that simple async functions are implemented on top of + // AsyncIterator objects; they just return a Promise for the value of + // the final result produced by the iterator. + + exports.async = function (innerFn, outerFn, self, tryLocsList, PromiseImpl) { + if (PromiseImpl === void 0) PromiseImpl = Promise; + var iter = new AsyncIterator(wrap(innerFn, outerFn, self, tryLocsList), PromiseImpl); + return exports.isGeneratorFunction(outerFn) ? iter // If outerFn is a generator, return the full iterator. + : iter.next().then(function (result) { + return result.done ? result.value : iter.next(); + }); + }; + + function makeInvokeMethod(innerFn, self, context) { + var state = GenStateSuspendedStart; + return function invoke(method, arg) { + if (state === GenStateExecuting) { + throw new Error("Generator is already running"); + } + + if (state === GenStateCompleted) { + if (method === "throw") { + throw arg; + } // Be forgiving, per 25.3.3.3.3 of the spec: + // https://people.mozilla.org/~jorendorff/es6-draft.html#sec-generatorresume + + + return doneResult(); + } + + context.method = method; + context.arg = arg; + + while (true) { + var delegate = context.delegate; + + if (delegate) { + var delegateResult = maybeInvokeDelegate(delegate, context); + + if (delegateResult) { + if (delegateResult === ContinueSentinel) continue; + return delegateResult; + } + } + + if (context.method === "next") { + // Setting context._sent for legacy support of Babel's + // function.sent implementation. + context.sent = context._sent = context.arg; + } else if (context.method === "throw") { + if (state === GenStateSuspendedStart) { + state = GenStateCompleted; + throw context.arg; + } + + context.dispatchException(context.arg); + } else if (context.method === "return") { + context.abrupt("return", context.arg); + } + + state = GenStateExecuting; + var record = tryCatch(innerFn, self, context); + + if (record.type === "normal") { + // If an exception is thrown from innerFn, we leave state === + // GenStateExecuting and loop back for another invocation. + state = context.done ? GenStateCompleted : GenStateSuspendedYield; + + if (record.arg === ContinueSentinel) { + continue; + } + + return { + value: record.arg, + done: context.done + }; + } else if (record.type === "throw") { + state = GenStateCompleted; // Dispatch the exception by looping back around to the + // context.dispatchException(context.arg) call above. + + context.method = "throw"; + context.arg = record.arg; + } + } + }; + } // Call delegate.iterator[context.method](context.arg) and handle the + // result, either by returning a { value, done } result from the + // delegate iterator, or by modifying context.method and context.arg, + // setting context.delegate to null, and returning the ContinueSentinel. + + + function maybeInvokeDelegate(delegate, context) { + var method = delegate.iterator[context.method]; + + if (method === undefined$1) { + // A .throw or .return when the delegate iterator has no .throw + // method always terminates the yield* loop. + context.delegate = null; + + if (context.method === "throw") { + // Note: ["return"] must be used for ES3 parsing compatibility. + if (delegate.iterator["return"]) { + // If the delegate iterator has a return method, give it a + // chance to clean up. + context.method = "return"; + context.arg = undefined$1; + maybeInvokeDelegate(delegate, context); + + if (context.method === "throw") { + // If maybeInvokeDelegate(context) changed context.method from + // "return" to "throw", let that override the TypeError below. + return ContinueSentinel; + } + } + + context.method = "throw"; + context.arg = new TypeError("The iterator does not provide a 'throw' method"); + } + + return ContinueSentinel; + } + + var record = tryCatch(method, delegate.iterator, context.arg); + + if (record.type === "throw") { + context.method = "throw"; + context.arg = record.arg; + context.delegate = null; + return ContinueSentinel; + } + + var info = record.arg; + + if (!info) { + context.method = "throw"; + context.arg = new TypeError("iterator result is not an object"); + context.delegate = null; + return ContinueSentinel; + } + + if (info.done) { + // Assign the result of the finished delegate to the temporary + // variable specified by delegate.resultName (see delegateYield). + context[delegate.resultName] = info.value; // Resume execution at the desired location (see delegateYield). + + context.next = delegate.nextLoc; // If context.method was "throw" but the delegate handled the + // exception, let the outer generator proceed normally. If + // context.method was "next", forget context.arg since it has been + // "consumed" by the delegate iterator. If context.method was + // "return", allow the original .return call to continue in the + // outer generator. + + if (context.method !== "return") { + context.method = "next"; + context.arg = undefined$1; + } + } else { + // Re-yield the result returned by the delegate method. + return info; + } // The delegate iterator is finished, so forget it and continue with + // the outer generator. + + + context.delegate = null; + return ContinueSentinel; + } // Define Generator.prototype.{next,throw,return} in terms of the + // unified ._invoke helper method. + + + defineIteratorMethods(Gp); + define(Gp, toStringTagSymbol, "Generator"); // A Generator should always return itself as the iterator object when the + // @@iterator function is called on it. Some browsers' implementations of the + // iterator prototype chain incorrectly implement this, causing the Generator + // object to not be returned from this call. This ensures that doesn't happen. + // See https://github.com/facebook/regenerator/issues/274 for more details. + + Gp[iteratorSymbol] = function () { + return this; + }; + + Gp.toString = function () { + return "[object Generator]"; + }; + + function pushTryEntry(locs) { + var entry = { + tryLoc: locs[0] + }; + + if (1 in locs) { + entry.catchLoc = locs[1]; + } + + if (2 in locs) { + entry.finallyLoc = locs[2]; + entry.afterLoc = locs[3]; + } + + this.tryEntries.push(entry); + } + + function resetTryEntry(entry) { + var record = entry.completion || {}; + record.type = "normal"; + delete record.arg; + entry.completion = record; + } + + function Context(tryLocsList) { + // The root entry object (effectively a try statement without a catch + // or a finally block) gives us a place to store values thrown from + // locations where there is no enclosing try statement. + this.tryEntries = [{ + tryLoc: "root" + }]; + tryLocsList.forEach(pushTryEntry, this); + this.reset(true); + } + + exports.keys = function (object) { + var keys = []; + + for (var key in object) { + keys.push(key); + } + + keys.reverse(); // Rather than returning an object with a next method, we keep + // things simple and return the next function itself. + + return function next() { + while (keys.length) { + var key = keys.pop(); + + if (key in object) { + next.value = key; + next.done = false; + return next; + } + } // To avoid creating an additional object, we just hang the .value + // and .done properties off the next function object itself. This + // also ensures that the minifier will not anonymize the function. + + + next.done = true; + return next; + }; + }; + + function values(iterable) { + if (iterable) { + var iteratorMethod = iterable[iteratorSymbol]; + + if (iteratorMethod) { + return iteratorMethod.call(iterable); + } + + if (typeof iterable.next === "function") { + return iterable; + } + + if (!isNaN(iterable.length)) { + var i = -1, + next = function next() { + while (++i < iterable.length) { + if (hasOwn.call(iterable, i)) { + next.value = iterable[i]; + next.done = false; + return next; + } + } + + next.value = undefined$1; + next.done = true; + return next; + }; + + return next.next = next; + } + } // Return an iterator with no values. + + + return { + next: doneResult + }; + } + + exports.values = values; + + function doneResult() { + return { + value: undefined$1, + done: true + }; + } + + Context.prototype = { + constructor: Context, + reset: function (skipTempReset) { + this.prev = 0; + this.next = 0; // Resetting context._sent for legacy support of Babel's + // function.sent implementation. + + this.sent = this._sent = undefined$1; + this.done = false; + this.delegate = null; + this.method = "next"; + this.arg = undefined$1; + this.tryEntries.forEach(resetTryEntry); + + if (!skipTempReset) { + for (var name in this) { + // Not sure about the optimal order of these conditions: + if (name.charAt(0) === "t" && hasOwn.call(this, name) && !isNaN(+name.slice(1))) { + this[name] = undefined$1; + } + } + } + }, + stop: function () { + this.done = true; + var rootEntry = this.tryEntries[0]; + var rootRecord = rootEntry.completion; + + if (rootRecord.type === "throw") { + throw rootRecord.arg; + } + + return this.rval; + }, + dispatchException: function (exception) { + if (this.done) { + throw exception; + } + + var context = this; + + function handle(loc, caught) { + record.type = "throw"; + record.arg = exception; + context.next = loc; + + if (caught) { + // If the dispatched exception was caught by a catch block, + // then let that catch block handle the exception normally. + context.method = "next"; + context.arg = undefined$1; + } + + return !!caught; + } + + for (var i = this.tryEntries.length - 1; i >= 0; --i) { + var entry = this.tryEntries[i]; + var record = entry.completion; + + if (entry.tryLoc === "root") { + // Exception thrown outside of any try block that could handle + // it, so set the completion value of the entire function to + // throw the exception. + return handle("end"); + } + + if (entry.tryLoc <= this.prev) { + var hasCatch = hasOwn.call(entry, "catchLoc"); + var hasFinally = hasOwn.call(entry, "finallyLoc"); + + if (hasCatch && hasFinally) { + if (this.prev < entry.catchLoc) { + return handle(entry.catchLoc, true); + } else if (this.prev < entry.finallyLoc) { + return handle(entry.finallyLoc); + } + } else if (hasCatch) { + if (this.prev < entry.catchLoc) { + return handle(entry.catchLoc, true); + } + } else if (hasFinally) { + if (this.prev < entry.finallyLoc) { + return handle(entry.finallyLoc); + } + } else { + throw new Error("try statement without catch or finally"); + } + } + } + }, + abrupt: function (type, arg) { + for (var i = this.tryEntries.length - 1; i >= 0; --i) { + var entry = this.tryEntries[i]; + + if (entry.tryLoc <= this.prev && hasOwn.call(entry, "finallyLoc") && this.prev < entry.finallyLoc) { + var finallyEntry = entry; + break; + } + } + + if (finallyEntry && (type === "break" || type === "continue") && finallyEntry.tryLoc <= arg && arg <= finallyEntry.finallyLoc) { + // Ignore the finally entry if control is not jumping to a + // location outside the try/catch block. + finallyEntry = null; + } + + var record = finallyEntry ? finallyEntry.completion : {}; + record.type = type; + record.arg = arg; + + if (finallyEntry) { + this.method = "next"; + this.next = finallyEntry.finallyLoc; + return ContinueSentinel; + } + + return this.complete(record); + }, + complete: function (record, afterLoc) { + if (record.type === "throw") { + throw record.arg; + } + + if (record.type === "break" || record.type === "continue") { + this.next = record.arg; + } else if (record.type === "return") { + this.rval = this.arg = record.arg; + this.method = "return"; + this.next = "end"; + } else if (record.type === "normal" && afterLoc) { + this.next = afterLoc; + } + + return ContinueSentinel; + }, + finish: function (finallyLoc) { + for (var i = this.tryEntries.length - 1; i >= 0; --i) { + var entry = this.tryEntries[i]; + + if (entry.finallyLoc === finallyLoc) { + this.complete(entry.completion, entry.afterLoc); + resetTryEntry(entry); + return ContinueSentinel; + } + } + }, + "catch": function (tryLoc) { + for (var i = this.tryEntries.length - 1; i >= 0; --i) { + var entry = this.tryEntries[i]; + + if (entry.tryLoc === tryLoc) { + var record = entry.completion; + + if (record.type === "throw") { + var thrown = record.arg; + resetTryEntry(entry); + } + + return thrown; + } + } // The context.catch method must only be called with a location + // argument that corresponds to a known catch block. + + + throw new Error("illegal catch attempt"); + }, + delegateYield: function (iterable, resultName, nextLoc) { + this.delegate = { + iterator: values(iterable), + resultName: resultName, + nextLoc: nextLoc + }; + + if (this.method === "next") { + // Deliberately forget the last sent value so that we don't + // accidentally pass it on to the delegate. + this.arg = undefined$1; + } + + return ContinueSentinel; + } + }; // Regardless of whether this script is executing as a CommonJS module + // or not, return the runtime object so that we can declare the variable + // regeneratorRuntime in the outer scope, which allows this module to be + // injected easily by `bin/regenerator --include-runtime script.js`. + + return exports; + }( // If this script is executing as a CommonJS module, use module.exports + // as the regeneratorRuntime namespace. Otherwise create a new empty + // object. Either way, the resulting object will be used to initialize + // the regeneratorRuntime variable at the top of this file. + module.exports ); + + try { + regeneratorRuntime = runtime; + } catch (accidentalStrictMode) { + // This module should not be running in strict mode, so the above + // assignment should always work unless something is misconfigured. Just + // in case runtime.js accidentally runs in strict mode, we can escape + // strict mode using a global Function call. This could conceivably fail + // if a Content Security Policy forbids using Function, but in that case + // the proper solution is to fix the accidental strict mode problem. If + // you've misconfigured your bundler to force strict mode and applied a + // CSP to forbid Function, and you're not willing to fix either of those + // problems, please detail your unique predicament in a GitHub issue. + Function("r", "regeneratorRuntime = r")(runtime); + } + }); + + var regenerator = runtime_1; + + var htmlSafe = function () { + var $el = $('
      '); + return function (text) { + return $el.text(text).html(); + }; + }(); + + var defaults = { + readonly: false, + key: 'state', + name: 'board', + message: { + loading: 'loading ...', + stateDisabled: 'Current issue cannot switch to this state', + allComplete: 'Showing all issues', + empty: 'There are no issues here', + btnSetFirst: 'Move it to the first', + btnSetLast: 'Move it to the last' + }, + className: { + iconComment: 'icon comments outline', + iconAngleLeft: 'icon angle double left', + iconAngleRight: 'icon angle double right', + iconIssue: 'icon sticky note outline', + card: 'ui link card', + action: 'ui button', + actions: 'ui mini basic icon buttons', + avatar: 'ui avatar image' + }, + labelsTemplate: function labelsTemplate(label) { + return " \n ").concat(htmlSafe(label.name), "\n "); + }, + actions: function actions(config) { + if (!config.plugins.Sortable) { + return []; + } + + return [{ + id: 'btn-set-first', + "class": config.className.action, + icon: config.className.iconAngleLeft, + title: config.message.btnSetFirst, + callback: function callback(boards, board) { + var state = board.state.toString(); + var states = boards.sortable.toArray(); + var i = states.indexOf(state); + + if (i >= 0) { + states.splice(i, 1); + states.splice(0, 0, state); + boards.sortable.sort(states); + config.onSorted(states); + boards.load(); + } + } + }, { + id: 'btn-set-last', + "class": config.className.action, + icon: config.className.iconAngleRight, + title: config.message.btnSetLast, + callback: function callback(boards, board) { + var state = board.state.toString(); + var states = boards.sortable.toArray(); + var i = states.indexOf(state); + + if (i >= 0) { + states.splice(i, 1); + states.push(state); + boards.sortable.sort(states); + config.onSorted(states); + boards.load(); + } + } + }]; + }, + data: [{ + order: 1, + name: 'Backlog', + state: 'open', + color: '#ffa726', + issuesCount: 0 + }, { + order: 2, + name: 'Done', + state: 'closed', + color: '#2baf2b', + issuesCount: 0 + }], + plugins: {}, + types: [], + user: { + id: 0, + admin: false + }, + + /** + * 在任务列表加载完后的回调 + * @callback BoardLoadCallback + * @param {Array} issues 任务列表 + * @param {Number} count 任务总数 + */ + + /** + * 在开始加载任务列表时的回调 + * @param {Object,Board} board 板块对象 + * @param {BoardLoadCallback} callback 用于接收任务列表的回调函数 + */ + onLoad: function onLoad(board, callback) { + $.ajax({ + url: 'issues', + data: { + state: board.state, + page: board.page + } + }).done(function () { + callback([], 0); + }).fail(function () { + callback([], 0); + }); + }, + + /** + * 在更新任务时的回调 + * @param {Object} issue 任务 + * @param {String,Number} oldState 更新前的状态 + */ + onUpdate: function onUpdate(issue, oldState) { + var _this = this; + + $.ajax({ + type: 'PUT', + url: issue.url, + data: { + state: issue.state + } + }).done(function (res) { + _this.updateIssue(res); + }).fail(function () { + _this.setIssueState(issue.id, oldState); + }); + }, + + /** + * 在渲染任务卡片时的回调 + * @param {Object} issue 任务 + * @param {JQuery} $el 任务卡片 + */ + onRender: function onRender(issue, $el) { + $el.addClass("issue-state-".concat(issue.state)); + return $el; + }, + + /** + * 在板块被排序后的回调 + * @param {Array} states 状态列表 + */ + onSorted: function onSorted(states) { + window.console.log(states); + } + }; + var Config = function Config(config) { + _classCallCheck(this, Config); + + $.extend(this, defaults, config); + + if (config.className) { + this.className = $.extend({}, defaults.className, config.className); + } + + if (config.message) { + this.message = $.extend({}, defaults.message, config.message); + } + }; + + var _typeof_1 = createCommonjsModule(function (module) { + function _typeof(obj) { + "@babel/helpers - typeof"; + + if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { + module.exports = _typeof = function _typeof(obj) { + return typeof obj; + }; + + module.exports["default"] = module.exports, module.exports.__esModule = true; + } else { + module.exports = _typeof = function _typeof(obj) { + return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; + }; + + module.exports["default"] = module.exports, module.exports.__esModule = true; + } + + return _typeof(obj); + } + + module.exports = _typeof; + module.exports["default"] = module.exports, module.exports.__esModule = true; + }); + + unwrapExports(_typeof_1); + + var assertThisInitialized = createCommonjsModule(function (module) { + function _assertThisInitialized(self) { + if (self === void 0) { + throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); + } + + return self; + } + + module.exports = _assertThisInitialized; + module.exports["default"] = module.exports, module.exports.__esModule = true; + }); + unwrapExports(assertThisInitialized); + + var possibleConstructorReturn = createCommonjsModule(function (module) { + var _typeof = _typeof_1["default"]; + + function _possibleConstructorReturn(self, call) { + if (call && (_typeof(call) === "object" || typeof call === "function")) { + return call; + } + + return assertThisInitialized(self); + } + + module.exports = _possibleConstructorReturn; + module.exports["default"] = module.exports, module.exports.__esModule = true; + }); + var _possibleConstructorReturn = unwrapExports(possibleConstructorReturn); + + var getPrototypeOf = createCommonjsModule(function (module) { + function _getPrototypeOf(o) { + module.exports = _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { + return o.__proto__ || Object.getPrototypeOf(o); + }; + module.exports["default"] = module.exports, module.exports.__esModule = true; + return _getPrototypeOf(o); + } + + module.exports = _getPrototypeOf; + module.exports["default"] = module.exports, module.exports.__esModule = true; + }); + var _getPrototypeOf = unwrapExports(getPrototypeOf); + + var setPrototypeOf = createCommonjsModule(function (module) { + function _setPrototypeOf(o, p) { + module.exports = _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { + o.__proto__ = p; + return o; + }; + + module.exports["default"] = module.exports, module.exports.__esModule = true; + return _setPrototypeOf(o, p); + } + + module.exports = _setPrototypeOf; + module.exports["default"] = module.exports, module.exports.__esModule = true; + }); + unwrapExports(setPrototypeOf); + + var inherits = createCommonjsModule(function (module) { + function _inherits(subClass, superClass) { + if (typeof superClass !== "function" && superClass !== null) { + throw new TypeError("Super expression must either be null or a function"); + } + + subClass.prototype = Object.create(superClass && superClass.prototype, { + constructor: { + value: subClass, + writable: true, + configurable: true + } + }); + if (superClass) setPrototypeOf(subClass, superClass); + } + + module.exports = _inherits; + module.exports["default"] = module.exports, module.exports.__esModule = true; + }); + var _inherits = unwrapExports(inherits); + + var Renderer = + /*#__PURE__*/ + function () { + function Renderer(config) { + _classCallCheck(this, Renderer); + + this.config = config; + } + + _createClass(Renderer, [{ + key: "getAvatarUrl", + value: function getAvatarUrl(name, avatarUrl) { + var Avatar = this.config.plugins.LetterAvatar; + + if (!avatarUrl || avatarUrl.indexOf('no_portrait.png') === 0) { + if (Avatar) { + return Avatar(name); + } + } + + return avatarUrl; + } + }, { + key: "getCardId", + value: function getCardId(issue) { + if (this.config.getIusseId) { + return this.config.getIusseId(issue); + } + + return 'issue-card-' + issue.id; + } + }]); + + return Renderer; + }(); + + /* eslint-disable indent */ + + function getUserUrl(user) { + return user.html_url || user.path; + } + + function renderCardUserLabel(issue) { + if (!issue.author) { + return ''; + } + + if (typeof issue.author.is_member !== 'undefined') { + if (!issue.author.is_member) { + return '[访客]'; + } + } + + if (issue.author.outsourced) { + return '[外包]'; + } + + return ''; + } + + function renderCardLabels(issue, labelsTemplate) { + if (!issue.labels || !labelsTemplate) { + return ''; + } + + var html = issue.labels.map(labelsTemplate).join(''); + return "
      ".concat(html, "
      "); + } + + var CardRenderer = + /*#__PURE__*/ + function (_Renderer) { + _inherits(CardRenderer, _Renderer); + + function CardRenderer() { + _classCallCheck(this, CardRenderer); + + return _possibleConstructorReturn(this, _getPrototypeOf(CardRenderer).apply(this, arguments)); + } + + _createClass(CardRenderer, [{ + key: "render", + value: function render(issue) { + var user = this.config.user; + var readonly = this.config.readonly; + var draggable = ''; + var cardClass = this.config.className.card; + + if (!readonly && (user.admin || user.id === issue.author.id)) { + draggable = 'draggable="true"'; + cardClass += ' card-draggable'; + } + + return "
    • \n
      \n \n ").concat(htmlSafe(issue.title), "\n \n ").concat(this.config.topLevelLabel && this.config.topLevelLabel(issue) || '', "\n ").concat(this.config.priorityLabel && this.config.priorityLabel(issue) || '', "\n
      \n
      \n ").concat(this.renderAssignee(issue), "\n ").concat(this.renderState(issue), "\n ").concat(renderCardLabels(issue, this.config.labelsTemplate), "\n #").concat(issue.number, "\n ").concat(renderCardUserLabel(issue), "\n ").concat(this.renderComments(issue), "\n
      \n
    • "); + } + }, { + key: "renderState", + value: function renderState(issue) { + var state = issue.state_data; + + if (!state || this.config.key === 'state') { + return ''; + } + + return "
      \n \n
      "); + } + }, { + key: "renderAssignee", + value: function renderAssignee(issue) { + var user = issue.assignee; + + if (!user || !user.id || this.config.key !== 'state') { + return ''; + } + + return "
      \n \n \"").concat(htmlSafe(user.name),\n \n
      "); + } + }, { + key: "renderComments", + value: function renderComments(issue) { + var className = this.config.className.iconComment; + + if (!issue.comments) { + return ''; + } + + return "").concat(issue.comments, ""); + } + }]); + + return CardRenderer; + }(Renderer); + + function setColorAlpha(color, alpha) { + var reg = /^#([\da-fA-F]{2})([\da-fA-F]{2})([\da-fA-F]{2})$/; + var matches = reg.exec(color); + var r = parseInt(matches[1], 16); + var g = parseInt(matches[2], 16); + var b = parseInt(matches[3], 16); + return "rgba(".concat(r, ",").concat(g, ",").concat(b, ",").concat(alpha, ")"); + } + + function renderBoardIcon(board) { + if (board.icon) { + return ""); + } + + return ''; + } + + var BoardRenderer = + /*#__PURE__*/ + function (_Renderer) { + _inherits(BoardRenderer, _Renderer); + + function BoardRenderer() { + _classCallCheck(this, BoardRenderer); + + return _possibleConstructorReturn(this, _getPrototypeOf(BoardRenderer).apply(this, arguments)); + } + + _createClass(BoardRenderer, [{ + key: "render", + value: function render(board) { + return "
      \n
      \n ").concat(this.renderHeader(board), "\n
      \n
        \n
        \n
        \n
        \n
        \n

        \n

        ").concat(this.config.message.stateDisabled, "

        \n
        \n
        \n
        \n
        "); + } + }, { + key: "renderHeader", + value: function renderHeader(board) { + var headerStyle = ''; + var headerClass = 'board-header'; + + if (board.color) { + if (board.colorTarget === 'background') { + headerStyle = "background-color: ".concat(setColorAlpha(board.color, 0.04)); + } else { + headerClass += ' has-border'; + headerStyle = "border-color: ".concat(board.color); + } + } + + return "
        \n

        \n ").concat(this.renderActions(), "\n ").concat(this.renderAvatar(board), "\n ").concat(renderBoardIcon(board), "\n ").concat(htmlSafe(board.name), "\n \n ").concat(board.issuesCount, "\n \n

        \n
        "); + } + }, { + key: "renderActions", + value: function renderActions() { + var config = this.config; + var actions = config.actions; + + if (typeof actions === 'function') { + actions = actions(config); + } + + return "
        \n ").concat(actions.map(function (a) { + return ""); + }).join(''), "\n
        "); + } + }, { + key: "renderAvatar", + value: function renderAvatar(board) { + if (!board.avatarUrl) { + return ''; + } + + return "\"").concat(board.state,"); + } + }, { + key: "renderTip", + value: function renderTip(board) { + var msg = this.config.message; + + if (board.loadable) { + return "
      • \n \n ".concat(msg.loading, "\n
      • "); + } + + if (board.completed && board.issues.length > 0) { + return "
      • ".concat(msg.allComplete, "
      • "); + } + + return "
      • ".concat(msg.empty, "
      • "); + } + }]); + + return BoardRenderer; + }(Renderer); + var Board = + /*#__PURE__*/ + function () { + function Board(data, config) { + var _this = this; + + _classCallCheck(this, Board); + + this.page = 0; + this.loadable = true; + this.loading = false; + this.completed = false; + this.issues = []; + this.name = data.name; + this.icon = data.icon; + this.state = data.state; + this.color = data.color; + this.colorTarget = data.colorTarget; + this.issuesCount = data.issuesCount || 0; + this.avatarUrl = data.avatarUrl; + this.config = config; + this.renderer = new BoardRenderer(config); + this.cardRenderer = new CardRenderer(config); + this.$tip = null; + this.$el = $(this.renderer.render(this)); + this.$dimmer = this.$el.find('.ui.dimmer'); + this.$issues = this.$el.find('.board-list'); + this.$issuesCount = this.$el.find('.issues-count'); + this.$issues.on('scroll', function () { + _this.autoload(); + }); + } + + _createClass(Board, [{ + key: "add", + value: function add(issue) { + this.issues.push(issue); + this.issuesCount += 1; + this.$issuesCount.text(this.issuesCount); + } + }, { + key: "find", + value: function find(id) { + for (var i = 0; i < this.issues.length; ++i) { + var issue = this.issues[i]; + + if (issue.id === id) { + return i; + } + } + + return -1; + } + }, { + key: "get", + value: function get(id) { + var i = this.find(id); + + if (i >= 0) { + return this.issues[i]; + } + + return null; + } + }, { + key: "remove", + value: function remove(id) { + var i = this.find(id); + + if (i >= 0) { + this.issuesCount -= 1; + this.$issuesCount.text(this.issuesCount); + return this.issues.splice(i, 1); + } + + return null; + } + }, { + key: "clear", + value: function clear() { + this.page = 0; + this.issues = []; + this.issuesCount = 0; + this.loading = false; + this.loadable = true; + this.completed = false; + this.$issuesCount.text(0); + this.$issues.empty(); + this.$tip = null; + } + }, { + key: "autoload", + value: function autoload() { + if (this.completed) { + return; + } + + if (!this.$tip || this.$tip.position().top < this.$issues.height()) { + this.load(); + } + } + }, { + key: "load", + value: function load() { + if (this.loading) { + return false; + } + + this.page += 1; + this.loading = true; + + if (this.page === 1) { + this.$dimmer.addClass('active'); + } + + this.config.onLoad(this, this.onLoadDone.bind(this)); + return true; + } + }, { + key: "onLoadDone", + value: function onLoadDone(issues, count) { + this.issuesCount = count; + this.$issuesCount.text(this.issuesCount); + this.appendIssues(issues); + + if (this.issuesCount > 0) { + if (issues.length < 1 || this.issuesCount === issues.length) { + this.loadable = false; + this.completed = true; + } else { + this.loadable = true; + this.completed = false; + } + } else { + this.loadable = false; + this.completed = true; + } + + if (this.page === 1) { + this.$dimmer.removeClass('active'); + } + + this.loading = false; + this.updateTip(); + this.autoload(); + } + /* 进行初次加载 */ + + }, { + key: "firstload", + value: function firstload() { + if (this.page > 0) { + return false; + } + + return this.load(); + } + /** + * 更新提示 + */ + + }, { + key: "updateTip", + value: function updateTip() { + if (this.$tip) { + this.$tip.remove(); + } + + this.$tip = $(this.renderer.renderTip(this)); + this.$issues.append(this.$tip); + } + }, { + key: "createCard", + value: function createCard(issue) { + var $card = $(this.cardRenderer.render(issue)); + var onSelect = this.config.onSelect; + + if (onSelect) { + $card.on('click', function (e) { + var $target = $(e.target); + + if (!$target.is('a')) { + $target = $target.parent(); + } + + if (!$target.parent().hasClass('card-header') && $target.is('a') && $target.attr('href')) { + return; + } + + onSelect(issue, e); + }); + } + + return this.config.onRender(issue, $card, this.config); + } + }, { + key: "appendIssue", + value: function appendIssue(issue) { + this.issues.push(issue); + this.$issues.append(this.createCard(issue)); + } + }, { + key: "prependIssue", + value: function prependIssue(issue) { + this.issuesCount += 1; + this.issues.splice(0, 0, issue); + this.$issues.prepend(this.createCard(issue)); + this.$issuesCount.text(this.issuesCount); + } + }, { + key: "updateIssue", + value: function updateIssue(issue) { + var $issue = $("#".concat(this.config.name, "-issue-").concat(issue.id)); + + if ($issue.length < 1) { + this.prependIssue(issue); + return; + } + + $issue.before(this.createCard(issue)).remove(); + } + /** + * 直接追加多个任务,不更新任务总数 + * @param {Array} issues 任务列表 + */ + + }, { + key: "appendIssues", + value: function appendIssues(issues) { + var _this2 = this; + + issues.filter(function (issue) { + return _this2.issues.every(function (boardIssue) { + return boardIssue.id !== issue.id; + }); + }).forEach(function (issue) { + issue[_this2.config.Key] = _this2.state; + + _this2.appendIssue(issue); + }); + } + }]); + + return Board; + }(); + + var Boards = + /*#__PURE__*/ + function () { + /** + * 创建一个看板 + * @param {JQuery} $el 看板容器元素 + * @param {BoardsSettings} options 配置 + */ + function Boards($el, options) { + _classCallCheck(this, Boards); + + var config = new Config(options); + this.$el = $el; + this.config = config; + this.boards = {}; + this.$hoverIssue = null; + this.$selectedIssue = null; + this.timerForScrollLoad = null; + this.bindDrag(); + this.bindScroll(); + this.initPlugins(); + this.setData(config.data); + } + + _createClass(Boards, [{ + key: "initPlugins", + value: function initPlugins() { + this.initSortable(); + } // 初始化拖拽排序功能 + + }, { + key: "initSortable", + value: function initSortable() { + var that = this; + var Sortable = that.config.plugins.Sortable; // 如果没有注入 SortableJS 依赖,则不启用这个功能 + + if (!Sortable) { + return false; + } + + that.$el.addClass('boards-sortable'); + that.sortable = Sortable.create(that.$el[0], { + handle: '.board-title', + dataIdAttr: 'data-state', + onUpdate: function onUpdate() { + that.config.onSorted(that.sortable.toArray()); + } + }); + that.$el.on('click', '.board-action', function (e) { + var $target = $(this); + var id = $target.data('id'); + var state = $target.parents('.board').data('state'); + var actions = that.config.actions; + + if (typeof actions === 'function') { + actions = actions(that.config); + } + + actions.some(function (action) { + if (action.id === id && action.callback) { + action.callback(that, that.boards[state], e); + return true; + } + + return false; + }); + }); + return true; + } + }, { + key: "bindScroll", + value: function bindScroll() { + var that = this; + var timerForScrollLoad = null; + + function onScrollLoad() { + if (timerForScrollLoad) { + clearTimeout(timerForScrollLoad); + } + + timerForScrollLoad = setTimeout(function () { + timerForScrollLoad = null; + that.load(); + }, 200); + } + + $(window).on('resize', onScrollLoad); + this.$el.on('scroll', onScrollLoad); + } + }, { + key: "bindDrag", + value: function bindDrag() { + var that = this; + + if (that.config.readonly) { + return; + } + + that.$el.on('dragstart', '.card', function (e) { + var issueId = $(this).data('id'); + var issue = that.getIssue(issueId); + + if (issue) { + that.setFocus(issue.type, issue.state); + } + + that.$selectedIssue = $(this); + e.originalEvent.dataTransfer.setData('text/plain', issueId); + e.stopPropagation(); + }); + that.$el.on('dragend', '.card', function () { + that.clearFocus(); + }); + that.$el.on('drop', '.board-list', function (e) { + e.preventDefault(); + e.stopPropagation(); + + if (that.$hoverIssue) { + that.$hoverIssue.removeClass('card-dragover'); + } + + if (!that.$selectedIssue) { + return false; + } + + if (that.config.readonly) { + return false; + } + + var $issue = that.$selectedIssue; + var issueId = $issue.data('id'); + var $board = $(this).parents('.board'); + var state = $board.data('state'); + var oldState = $issue.parents('.board').data('state'); + var nextIssueId = that.$hoverIssue ? that.$hoverIssue.data('id') : null; + that.setIssueState(issueId, state, nextIssueId, function _callee(issue) { + return regenerator.async(function _callee$(_context) { + while (1) { + switch (_context.prev = _context.next) { + case 0: + return _context.abrupt("return", that.config.onUpdate(issue, oldState, nextIssueId)); + + case 1: + case "end": + return _context.stop(); + } + } + }); + }); + return true; + }); + that.$el.on('dragover', '.board-list', function (e) { + var key = that.config.key; + var $target = $(e.target); + + if (!that.$selectedIssue) { + return; + } + + e.preventDefault(); + + while ($target.length > 0 && !$target.hasClass('card')) { + $target = $target.parent(); + } + + if ($target.length < 1) { + if (that.$hoverIssue) { + that.$hoverIssue.removeClass('card-dragover'); + } + + that.$hoverIssue = null; + return; + } + + if (that.$hoverIssue) { + that.$hoverIssue.removeClass('card-dragover'); + } + + that.$hoverIssue = $target; + var hoverIssue = that.getIssue($target.data('id')); + var selectedIssue = that.getIssue(that.$selectedIssue.data('id')); + + if (hoverIssue && selectedIssue && hoverIssue[key] !== selectedIssue[key]) { + that.$hoverIssue.addClass('card-dragover'); + } + }); + } + /** + * 设置焦点板块 + * 根据指定的类型和状态,排除无关状态的板块 + * @param {String, Number} typeId 任务类型 id + * @param {String, Number} stateId 任务状态 id + */ + + }, { + key: "setFocus", + value: function setFocus(typeId, stateId) { + var _this = this; + + var stateIds = []; + var issueType = null; + + if (this.config.key !== 'state') { + return; + } + + this.config.types.some(function (t) { + if (t.id === typeId) { + issueType = t; + return true; + } + + return false; + }); + + if (issueType) { + stateIds = issueType.states.map(function (state) { + return state.id.toString(); + }); + } + + Object.keys(this.boards).forEach(function (id) { + if (id !== stateId.toString() && stateIds.indexOf(id) === -1) { + _this.boards[id].$el.addClass('board-blur'); + } + }); + } + /* 清除板块的焦点效果 */ + + }, { + key: "clearFocus", + value: function clearFocus() { + var _this2 = this; + + Object.keys(this.boards).forEach(function (key) { + _this2.boards[key].$el.removeClass('board-blur'); + }); + } + }, { + key: "getIssueCard", + value: function getIssueCard(id) { + return $("#".concat(this.config.name, "-issue-").concat(id)); + } + }, { + key: "getIssue", + value: function getIssue(id) { + var $issue = this.getIssueCard(id); + var $board = $issue.parents('.board'); + var state = $board.data('state'); + var board = this.boards[state]; + + if (board) { + return board.get(id); + } + + return null; + } + }, { + key: "removeIssue", + value: function removeIssue(id) { + var issue = null; + var $issue = this.getIssueCard(id); + + if ($issue.length < 1) { + return issue; + } + + var state = $issue.parents('.board').data('state'); + + if (state) { + var board = this.boards[state]; + + if (board) { + issue = board.remove(id); + } + } + + $issue.remove(); + return issue; + } + }, { + key: "updateIssue", + value: function updateIssue(issue) { + var board = this.boards[issue[this.config.key]]; + + if (board) { + board.updateIssue(issue); + return true; + } + + return false; + } + }, { + key: "prependIssue", + value: function prependIssue(issue) { + var board = this.boards[issue[this.config.key]]; + + if (board) { + board.prependIssue(issue); + return true; + } + + return false; + } + }, { + key: "setIssueState", + value: function setIssueState(issueId, state, nextIssueId, callback) { + var $issue = this.getIssueCard(issueId); + var $nextIssue = nextIssueId ? this.getIssueCard(nextIssueId) : null; + + if ($issue.length < 1) { + return null; + } + + var user = this.config.user; + var $oldBoard = $issue.parents('.board'); + var oldState = $oldBoard.data('state'); + var oldBoard = this.boards[oldState]; + var newBoard = this.boards[state]; + + if (oldBoard.state === state) { + return null; + } // 如果新的板块不接受该状态的 issue + + + if (newBoard.exclude && newBoard.exclude.indexOf(oldState) >= 0) { + return null; + } + + var issue = oldBoard.get(issueId); // 如果当前用户既不具备管理权限,也不是 issue 作者,则禁止操作 + + if (!user.admin && issue.author.id !== user.id) { + return null; + } + + issue[this.config.key] = state; + newBoard.add(issue); + oldBoard.remove(issue.id); + $issue.hide(256, function () { + // 如果有指定下一个 issue,则将当前 issue 插入到它前面 + if ($nextIssue) { + $nextIssue.before($issue); + } else { + newBoard.$issues.prepend($issue); + } + + $issue.addClass('card-loading'); + $issue.show(256, function _callee2() { + return regenerator.async(function _callee2$(_context2) { + while (1) { + switch (_context2.prev = _context2.next) { + case 0: + if (!callback) { + _context2.next = 3; + break; + } + + _context2.next = 3; + return regenerator.awrap(callback(issue)); + + case 3: + $issue.removeClass('card-loading'); + + case 4: + case "end": + return _context2.stop(); + } + } + }); + }); + }); + newBoard.updateTip(); + oldBoard.updateTip(); + oldBoard.autoload(); + return issue; + } + }, { + key: "load", + value: function load() { + var _this3 = this; + + var count = 0; + var bound = this.$el.offset(); // 设置边界框(可见区域)的尺寸 + + bound.width = this.$el.width(); + bound.height = this.$el.height(); + Object.keys(this.boards).forEach(function (state) { + var board = _this3.boards[state]; + var offset = board.$el.offset(); // 如果当前板块在可见区域内 + + if (offset.top + board.$el.height() > bound.top && offset.left + board.$el.width() > bound.left && offset.top < bound.top + bound.height && offset.left < bound.left + bound.width) { + if (board.firstload()) { + count += 1; + } + } + }); + return count; + } + }, { + key: "setData", + value: function setData(data) { + var _this4 = this; + + this.boards = {}; + this.$el.addClass('boards-list').empty(); + data.forEach(function (boardData) { + var board = new Board(boardData, _this4.config); + _this4.boards[boardData.state] = board; + + _this4.$el.append(board.$el); + }); + } + }, { + key: "clearData", + value: function clearData() { + var _this5 = this; + + Object.keys(this.boards).forEach(function (state) { + _this5.boards[state].clear(); + }); + } + }]); + + return Boards; + }(); + + $.fn.boards = function (options) { + var that = this.data('boards'); + var settings = $.extend({}, $.fn.boards.settings, options); + + if (!that) { + that = new Boards(this, settings); + this.data('boards', that); + that.load(); + } + + return this; + }; + + $.fn.boards.settings = defaults; }()); diff --git a/app/assets/stylesheets/gitee-frontend/components/boards.css b/app/assets/stylesheets/gitee-frontend/components/boards.css index 6f6f182e83c1ec869ce98cacf61e0bdcf01e11e2..1d9f0477ebfeae0db6b3493560affe04e04dedf3 100644 --- a/app/assets/stylesheets/gitee-frontend/components/boards.css +++ b/app/assets/stylesheets/gitee-frontend/components/boards.css @@ -78,17 +78,35 @@ padding-right: 3em; } +.boards-list .board-list .card-loading { + position: relative; + pointer-events: none; +} + +.boards-list .board-list .card-loading::before { + content: ''; + top: 0; + left: 0; + z-index: 1; + width: 100%; + height: 100%; + position: absolute; + background: rgba(255, 255, 255, 0.8); +} + .boards-list .board-list .button-wrapper { padding: 10px; text-align: center; } -.boards-list .board-list .card[draggable="true"], .boards-list .board-list .card-draggable { +.boards-list .board-list .card[draggable="true"], +.boards-list .board-list .card-draggable { cursor: move; cursor: -webkit-grab; } -.boards-list .board-list .card[draggable="true"]:active, .boards-list .board-list .card-draggable:active { +.boards-list .board-list .card[draggable="true"]:active, +.boards-list .board-list .card-draggable:active { cursor: -webkit-grabbing; } @@ -125,6 +143,7 @@ } .boards-list .board-list .labels { + margin-bottom: 16px; font-size: smaller; } @@ -137,6 +156,10 @@ margin: 0.4em 0.4em 0 0; } +.boards-list .board-list .labels:empty { + margin-bottom: 0px; +} + .boards-list .board-list .assignee, .boards-list .board-list .state { right: 1em;