├── static └── .gitkeep ├── .eslintignore ├── src ├── assets │ ├── fsm.png │ ├── logo.png │ ├── kanban.css │ └── kanban.scss ├── plugin.js ├── main.js ├── App.vue └── components │ └── Kanban.vue ├── .gitignore ├── config ├── prod.env.js ├── test.env.js ├── dev.env.js └── index.js ├── .editorconfig ├── .travis.yml ├── .postcssrc.js ├── index.html ├── .babelrc ├── docs ├── index.html └── static │ ├── js │ ├── manifest.2cafcc78e0c6c34e6ef6.js │ ├── app.7d106d57c92bbc79dd0b.js │ ├── manifest.2cafcc78e0c6c34e6ef6.js.map │ └── app.7d106d57c92bbc79dd0b.js.map │ └── css │ ├── app.0208ff01681785d21951f7ffc26b552c.css │ └── app.0208ff01681785d21951f7ffc26b552c.css.map ├── .eslintrc.js ├── LICENSE ├── test ├── vue-kanban.spec.js ├── __snapshots__ │ └── vue-kanban.spec.js.snap └── state-machine.spec.js ├── package.json └── README.md /static/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | build/*.js 2 | config/*.js 3 | -------------------------------------------------------------------------------- /src/assets/fsm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ethan0007/vue-kanban/master/src/assets/fsm.png -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ethan0007/vue-kanban/master/src/assets/logo.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | dist/ 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | test/unit/coverage 8 | -------------------------------------------------------------------------------- /config/prod.env.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | NODE_ENV: '"production"', 3 | build: { 4 | assetsPublicPath: '/vue-kanban/', 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /src/plugin.js: -------------------------------------------------------------------------------- 1 | import Kanban from './components/Kanban.vue'; 2 | 3 | export default { 4 | install(vue) { 5 | vue.component('kanban-board', Kanban); 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /config/test.env.js: -------------------------------------------------------------------------------- 1 | var merge = require('webpack-merge') 2 | var devEnv = require('./dev.env') 3 | 4 | module.exports = merge(devEnv, { 5 | NODE_ENV: '"testing"' 6 | }) 7 | -------------------------------------------------------------------------------- /config/dev.env.js: -------------------------------------------------------------------------------- 1 | var merge = require('webpack-merge') 2 | var prodEnv = require('./prod.env') 3 | 4 | module.exports = merge(prodEnv, { 5 | NODE_ENV: '"development"' 6 | }) 7 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "node" 4 | before_install: 5 | - curl -o- -L https://yarnpkg.com/install.sh | bash -s -- --version 0.27.5 6 | - export PATH="$HOME/.yarn/bin:$PATH" 7 | cache: yarn 8 | -------------------------------------------------------------------------------- /.postcssrc.js: -------------------------------------------------------------------------------- 1 | // https://github.com/michael-ciniawsky/postcss-load-config 2 | 3 | module.exports = { 4 | "plugins": { 5 | // to edit target browsers: use "browserlist" field in package.json 6 | "autoprefixer": {} 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | vue-kanban 6 | 7 | 8 |
9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["env", { "modules": false }], 4 | "stage-2" 5 | ], 6 | "plugins": ["transform-runtime"], 7 | "comments": false, 8 | "env": { 9 | "test": { 10 | "presets": ["env", "stage-2"], 11 | "plugins": [ "istanbul" ] 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | // The Vue build version to load with the `import` command 2 | // (runtime-only or standalone) has been set in webpack.base.conf with an alias. 3 | import Vue from 'vue'; 4 | import App from './App'; 5 | 6 | Vue.config.productionTip = false; 7 | 8 | /* eslint-disable no-new */ 9 | new Vue({ 10 | el: '#app', 11 | template: '', 12 | components: { App }, 13 | }); 14 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | vue-kanban
-------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | // http://eslint.org/docs/user-guide/configuring 2 | 3 | module.exports = { 4 | root: true, 5 | parser: 'babel-eslint', 6 | parserOptions: { 7 | sourceType: 'module' 8 | }, 9 | env: { 10 | browser: true, 11 | }, 12 | extends: 'airbnb-base', 13 | // required to lint *.vue files 14 | plugins: [ 15 | 'html' 16 | ], 17 | // check if imports actually resolve 18 | 'settings': { 19 | 'import/resolver': { 20 | 'webpack': { 21 | 'config': 'build/webpack.base.conf.js' 22 | } 23 | } 24 | }, 25 | // add your custom rules here 26 | 'rules': { 27 | // don't require .vue extension when importing 28 | 'import/extensions': ['error', 'always', { 29 | 'js': 'never', 30 | 'vue': 'never' 31 | }], 32 | // allow optionalDependencies 33 | 'import/no-extraneous-dependencies': ['error', { 34 | 'optionalDependencies': ['test/unit/index.js'] 35 | }], 36 | // allow debugger during development 37 | 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Brock Reece 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /docs/static/js/manifest.2cafcc78e0c6c34e6ef6.js: -------------------------------------------------------------------------------- 1 | !function(e){function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var r=window.webpackJsonp;window.webpackJsonp=function(t,c,u){for(var i,a,f,s=0,l=[];s', 8 | data() { 9 | return { 10 | stages: ['on-hold', 'in-progress', 'needs-review', 'approved'], 11 | blocks: [ 12 | { 13 | id: 1, 14 | status: 'on-hold', 15 | title: 'Test', 16 | }, 17 | ], 18 | config: { 19 | copy: true, 20 | direction: 'horizontal', 21 | }, 22 | }; 23 | }, 24 | }).$mount(); 25 | 26 | describe('VueKanban', () => { 27 | describe('installing plugin', () => { 28 | it('load component', () => { 29 | expect(typeof Vue.options.components['kanban-board']).toEqual('function'); 30 | }); 31 | }); 32 | 33 | describe('Handles props', () => { 34 | it('stages', () => { 35 | expect(typeof vm.$refs.kanban.stages).toEqual('object'); 36 | expect(vm.$refs.kanban.stages).toContain('approved'); 37 | }); 38 | 39 | it('blocks', () => { 40 | expect(typeof vm.$refs.kanban.blocks).toEqual('object'); 41 | expect(vm.$refs.kanban.blocks.map(b => b.id)).toContain(1); 42 | }); 43 | 44 | describe('config', () => { 45 | it('should be an object', () => { 46 | expect(typeof vm.$refs.kanban.config).toEqual('object'); 47 | }); 48 | 49 | it('should use values in prop', () => { 50 | expect(vm.$refs.kanban.config.copy).toEqual(true); 51 | expect(vm.$refs.kanban.config.direction).toEqual('horizontal'); 52 | }); 53 | 54 | it('should set accepts defaults', () => { 55 | expect(vm.$refs.kanban.config.accepts).toEqual(vm.$refs.kanban.accepts); 56 | }); 57 | it('should set the dragula defaults', () => { 58 | expect(vm.$refs.kanban.config.copySortSource).toEqual(false); 59 | }); 60 | }); 61 | }); 62 | 63 | describe('Assign to correct column', () => { 64 | it('stages', () => { 65 | expect(vm.$refs.kanban.getBlocks('on-hold').map(b => b.id)).toContain(1); 66 | }); 67 | 68 | it('should match snapshot', () => { 69 | expect(vm.$refs.kanban.$el).toMatchSnapshot(); 70 | }); 71 | }); 72 | 73 | describe('State machine config', () => { 74 | describe('no config', () => { 75 | test('machine should be null', () => { 76 | expect(vm.$refs.kanban.machine).toBe(null); 77 | }); 78 | 79 | test('accepts should return true', () => { 80 | expect(vm.$refs.kanban.accepts()).toBe(true); 81 | }); 82 | }); 83 | }); 84 | }); 85 | -------------------------------------------------------------------------------- /docs/static/css/app.0208ff01681785d21951f7ffc26b552c.css: -------------------------------------------------------------------------------- 1 | ul.drag-inner-list,ul.drag-list{list-style-type:none;margin:0;padding:0}.drag-container{max-width:1000px;margin:20px auto}.drag-list{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start}@media (max-width:690px){.drag-list{display:block}}.drag-column{-webkit-box-flex:1;-ms-flex:1;flex:1;margin:0 10px;position:relative;background:rgba(0,0,0,.2);overflow:hidden}@media (max-width:690px){.drag-column{margin-bottom:30px}}.drag-column h2{font-size:.8rem;margin:0;text-transform:uppercase;font-weight:600}.drag-column-header{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;padding:10px}.drag-inner-list{min-height:50px;color:#fff}.drag-item{padding:10px;margin:10px;height:100px;background:rgba(0,0,0,.4);transition:all .3s cubic-bezier(.23,1,.32,1)}.drag-item.is-moving{-webkit-transform:scale(1.5);transform:scale(1.5);background:rgba(0,0,0,.8)}.drag-header-more{cursor:pointer}.drag-options{position:absolute;top:44px;left:0;width:100%;height:100%;padding:10px;-webkit-transform:translateX(100%);transform:translateX(100%);opacity:0;transition:all .3s cubic-bezier(.23,1,.32,1)}.drag-options.active{-webkit-transform:translateX(0);transform:translateX(0);opacity:1}.drag-options-label{display:block;margin:0 0 5px}.drag-options-label input{opacity:.6}.drag-options-label span{display:inline-block;font-size:.9rem;font-weight:400;margin-left:5px}.gu-mirror{position:fixed!important;margin:0!important;z-index:9999!important;opacity:.8;list-style-type:none}.gu-hide{display:none!important}.gu-unselectable{-webkit-user-select:none!important;-moz-user-select:none!important;-ms-user-select:none!important;user-select:none!important}.gu-transit{opacity:.2}*{box-sizing:border-box}body{background:#33363d;color:#fff;font-family:Lato;font-weight:300;line-height:1.5;-webkit-font-smoothing:antialiased}.drag-column-on-hold .drag-column-header,.drag-column-on-hold .drag-options,.drag-column-on-hold .is-moved{background:#fb7d44}.drag-column-in-progress .drag-column-header,.drag-column-in-progress .drag-options,.drag-column-in-progress .is-moved{background:#2a92bf}.drag-column-needs-review .drag-column-header,.drag-column-needs-review .drag-options,.drag-column-needs-review .is-moved{background:#f4ce46}.drag-column-approved .drag-column-header,.drag-column-approved .drag-options,.drag-column-approved .is-moved{background:#00b961}.section{padding:20px;text-align:center}.section a{color:#fff;text-decoration:none;font-weight:300}.section h4{font-weight:400}.section h4 a{font-weight:600} -------------------------------------------------------------------------------- /test/__snapshots__/vue-kanban.spec.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`VueKanban Assign to correct column should match snapshot 1`] = ` 4 |
7 |
    10 |
  • 13 | 16 |

    17 | on-hold 18 |

    19 |
    20 | 21 |
    24 | 25 |
      29 |
    • 33 | 34 | on-hold 35 | 36 | 37 |
      38 | 1 39 |
      40 |
    • 41 |
    42 | 43 |
  • 47 |
  • 50 | 53 |

    54 | in-progress 55 |

    56 |
    57 | 58 |
    61 | 62 |
      66 | 67 |