Code Monkey home page Code Monkey logo

vue-kanban's Introduction

vue-kanban Build Status npm version

A drag and drop kanban board component

Installation

Vue CLI

You can install this plugin through the Vue CLI

vue add vue-cli-plugin-kanban

Manual installation

Add vue-kanban to your project with npm

npm install vue-kanban

... or yarn

yarn add vue-kanban

Then install the plugin in your entry file

import vueKanban from 'vue-kanban'

Vue.use(vueKanban)

Basic Usage

The kanban-board component has been added globally to your project and so can be used in your templates without having to explicitly import it.

<kanban-board :stages="stages" :blocks="blocks"></kanban-board>

Required Props

  • stages: an array of stages for the kanban board
  • blocks: an array of objects that will make up the blocks on the kanban board
{
  stages: ['on-hold', 'in-progress', 'needs-review', 'approved'],
  blocks: [
    {
      id: 1,
      status: 'on-hold',
      title: 'Test',
    },
  ],
}

Advanced Props

  • config: an object of dragula options to be passed to the kanban board, see dragula docs for more details
  • state-machine-config: an xstate config object that can be used to manage the kanban board, read here for more details
{
  config: {
    // Don't allow blocks to be moved out of the approved stage
    accepts(block, target, source) {
      return source.dataset.status !== 'approved',
    }
  }
}

Receiving Changes

The component will emit an event when a block is moved

<kanban-board :stages="stages" :blocks="blocks" @update-block="updateBlock"></kanban-board>
<script>
...
  methods: {
    updateBlock(id, status) {
      this.blocks.find(b => b.id === Number(id)).status = status;
    },
  },
...
</script>

Add some style

I have included a scss stylesheet in this repo as a starting point that can be used in your project

<style lang="scss">
  @import './assets/kanban.scss';
</style>

Customize the kanban blocks

Each block has a named slot which can be extended from the parent, like so...

<kanban-board :stages="stages" :blocks="blocks" @update-block="updateBlock">
  <div v-for="stage in stages" :slot="stage" :key="stage">
    <h2>{{ stage }}</h2>
  </div>
  <div v-for="block in blocks" :slot="block.id" :key="block.id">
    <div>
      <strong>id:</strong> {{ block.id }}
    </div>
    <div>
      {{ block.title }}
    </div>
  </div>
</kanban-board>

State machine

Vue-kanban is now compatible with xstate state machines.

You can pass an xstate config as a prop and the Kanban board will use the state machine to restrict which moves are allowed.

As an example we can achieve the following workflow

Read more words!

With the following config

stateMachineConfig: {
  id: 'kanban',
  initial: 'on-hold',
  states: {
    'on-hold': {
      on: {
        PICK_UP: 'in-progress',
      },
    },
    'in-progress': {
      on: {
        RELINQUISH_TASK: 'on-hold',
        PUSH_TO_QA: 'needs-review',
      },
    },
    'needs-review': {
      on: {
        REQUEST_CHANGE: 'in-progress',
        PASS_QA: 'approved',
      },
    },
    approved: {
      type: 'final',
    },
  },
},

vue-kanban's People

Contributors

brockreece avatar c2nprds avatar dependabot[bot] avatar gusthavosantana avatar jamacon36 avatar johfer-bd avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vue-kanban's Issues

Duplicate names in stages

It seems it identifies different columns by the stage name, it doesn't make sense, it is better to use id.

is-moved class

When dragging and dropping to a different column, I noticed that there is no is moved class attached the block that was just operated on. But however, it is attached when it is operated in the same column.

Error after installing the plugin through the Vue CLI

Hello,
I installed the plugin according to the documentation using
vue add vue-cli-plugin-kanban
But when I try to start the server I receive the following error:

Error: Cannot find module 'node_modules/vue-cli-plugin-kanban/generator.js'. Please verify that the package.json has a valid "main" entry
code: 'MODULE_NOT_FOUND',
path: 'node_modules/vue-cli-plugin-kanban/package.json',
requestPath: 'vue-cli-plugin-kanban'

Have a nice day,
Mihai

Connect two Kanban components

How to connect two Kanban components ?
If this is not possible right now, this could be a good enhancement for this library.

I need to use two separated kanban components, in such way one of them is hidden through a drawer. When dragging one card from the first kanban, I would like to drag it to the second one.

README Update

a key is now required in the v-for

<kanban-board :stages="stages" :blocks="blocks" @update-block="updateBlock">

{{ stage }}

id: {{ block.id }}
{{ block.title }}

failed to bild

installed via npm to my quasar projekt and ran quasar dev.
Build process failed with:
Module build failed: Error: Couldn't find preset "env" relative to directory ....

Any hints ?

brgds

Can't drag any card on Kanban

Well, I'm filling the stages and blocks properties in with dynamic data. So far, it's displaying exactly what I want but it seems that the draggable event is not working. Is there any workaround to this issue?

Template or render function not defined.

[Vue warn]: Failed to mount component: template or render function not defined.

found in

--->
at app/assets/javascripts/components/app/campaigns/canvas/kanban/canvas-kanban.vue
at app/assets/javascripts/components/app/app.vue

Template:

<template>
  <div v-if="loaded" class="kanban">
    <canvas-header></canvas-header>
    <kanban-board :stages="stages" :blocks="blocks"
      @update-flight-status="updateFlightStatus">
      <div v-for="block in blocks">
        <div>
          <strong>id:</strong> {{ block.id }}
        </div>
        <div>
          {{ block.title }}
        </div>
      </div>
    </kanban-board>
  </div>
  <full-loader v-else></full-loader>
</template>

Am i doing anything wrong?

add order by id

hi , how i order block in list with change orderid parametr?

can't updated config object dynamically

 <kanban-board
      class="kanban-board"
      :stages="leadStatusColumns"
      :blocks="blocksClone"
      :config="config"
      @update-block="updateBlock"
    >

im using config object which inside the data in vue.

data() {
    return {
      config: {
        accepts() {
          return true;
        }
      }
}
}

& im trying to update config object before component render by calling

beforeMount() {
this.updateConfig();
},

her is my update function for config :

updateConfig() {
let New = this.leadStatusLabels.New;
let Qualified = this.leadStatusLabels.Qualified;
let OnHold = this.leadStatusLabels.OnHold;
let Lodged = this.leadStatusLabels.Lodged;
let Approved = this.leadStatusLabels.Approved;
let Unsuccessful = this.leadStatusLabels.Unsuccessful;
let config = {
accepts(block, target, source) {
let decision = false;
if (source.dataset.status === New) {
if (
target.dataset.status === Qualified ||
target.dataset.status === OnHold ||
target.dataset.status === Unsuccessful
) {
decision = true;
}
} else if (source.dataset.status === Qualified) {
if (
target.dataset.status === OnHold ||
target.dataset.status === Lodged ||
target.dataset.status === Unsuccessful
) {
decision = true;
}
} else if (source.dataset.status === OnHold) {
if (
target.dataset.status === New ||
target.dataset.status === Qualified ||
target.dataset.status === Lodged ||
target.dataset.status === Approved ||
target.dataset.status === Unsuccessful
) {
decision = true;
}
} else if (source.dataset.status === Lodged) {
if (
target.dataset.status === OnHold ||
target.dataset.status === Approved ||
target.dataset.status === Unsuccessful
) {
decision = true;
}
} else if (source.dataset.status === Approved) {
if (target.dataset.status === OnHold) {
decision = true;
}
} else if (source.dataset.status === Unsuccessful) {
if (target.dataset.status === Qualified) {
decision = true;
}
}
return decision;
}
};
console.log(updated config , config);
this.config = config;
}

issue is i can't move my cards acording to above conditions. any support to update those config file dynamically?

ERROR in building process

ERROR in xxx from UglifyJs Unexpected token: punc (() [./node_modules/vue-kanban/src/plugin.js:4,0]

Plugin.js:

import Kanban from './components/Kanban';

export default {
  install(vue) {
    vue.component('kanban-board', Kanban);
  },
};

Using API Get to Populate Array Of Stages Does Not Get Passed to Dragula

Hey, @BrockReece thank you so much for the plugin! We ran into an issue getting stages from an API endpoint and figured a workaround to sanity check with you.

We found that if we used axios or fetch to populate the array of stages dragula doesn't see the updated list of on $refs in time when the Kanban component is mounted:

My Component Code

methods: {
    getStages() {
      const path = '/some/path/to/the/list';
      axios.get(path, (response) => {
        this.stages = response.data.stages;
      });
    },
}
created() {
    this.getStages();
}

We figured a workaround by adding an updated listener in Kanban.vue that uses dragula's containers API method to repopulate its list:

node-modules/vue-kanban/src/components/Kanban.vue

  updated() {
    this.drake.containers = this.$refs.list;
  },
  mounted() {
    this.drake = dragula(this.$refs.list)
      .on('drag', (el) => {
        el.classList.add('is-moving');
      })
      .on('drop', (block, list) => {
        let index = 0;
        for (index = 0; index < list.children.length; index += 1) {
          if (list.children[index].classList.contains('is-moving')) break;
        }
        this.$emit('update-block', block.dataset.blockId, list.dataset.status, index);
      })
      .on('dragend', (el) => {
        el.classList.remove('is-moving');

        window.setTimeout(() => {
          el.classList.add('is-moved');
          window.setTimeout(() => {
            el.classList.remove('is-moved');
          }, 600);
        }, 100);
      });
  }

Is there a better way to do this? I'd be happy to PR if it's non-breaking.

Thanks again!

项目中引入vue-kanban后报错,很奇怪的报错

vue项目中按照说明引入了vue-kanban,重启时页面报错如下
Uncaught SyntaxError: Unexpected token import

检查后发现
kanban.vue中
import dragula from 'dragula';这个组件引入失败,请教大神,这个怎么回事情。拜谢,大佬能否

Vuex example

Hi, can someone please provide a complete example including sorting and save/read data with vuex?

LICENSE

Can you add license, please

Component not rendering

So I've tried to install this a couple of times now, but no matter what I do I can't get it to render.

Here is my main.js file:

import './plugins/vuetify'
import App from './App.vue'
import router from './router'
import vueKanban from 'vue-kanban'

Vue.use(vueKanban)
Vue.config.productionTip = false

new Vue({
  router,
  render: h => h(App)
}).$mount('#app')

My kanban.vue:

<template>
    <v-container>
        <kanban :stages="stages" :blocks="blocks" @update-block="updateBlock">
            <div v-for="stage in stages" :slot="stage">
                <h2>{{ stage }}</h2>
            </div>
            <div v-for="block in blocks" :slot="block.id">
                <div>
                    <strong>id:</strong> {{ block.id }}
                </div>
                <div>
                    {{ block.title }}
                </div>
            </div>
        </kanban>
    </v-container>
</template>

<script>
     //Temp to see if needed to be given as a component
    import kanban from 'vue-kanban'
    export default {
        component:{
            kanban
        },
        data: {
                    stages: ['on-hold', 'in-progress', 'needs-review', 'approved'],
                        blocks: [
                    {
                        id: 1,
                        status: 'on-hold',
                        title: 'Test',
                    },
                            {
                                id: 2,
                                status: 'in-progress',
                                title: 'VIP',
                            },
                ],
                }
        }

</script>

<style scoped lang="scss">
    @import "../assets/kanban.scss";
</style>

But it does not render on the page, got any ideas?

Source for demo?

Hi, wondering where I could see the source for the demo page?
Thanks

Couldn't find preset stage-2

Installed via npm. When trying to load component I get an error when building via npm:

ERROR in ./node_modules/babel-loader/lib?{"cacheDirectory":true,"presets":[["env",{"modules":false,"targets":{"browsers":["> 2%"],"uglify":true}}]],"plugins":["transform-object-rest-spread",["transform-runtime",{"polyfill":false,"helpers":false}]]}!./node_modules/vue-loader/lib/selector.js?type=script&index=0!./node_modules/vue-kanban/src/components/Kanban.vue
Module build failed: Error: Couldn't find preset "stage-2" relative to directory "/srv/http/productionboard/node_modules/vue-kanban"
at /srv/http/productionboard/node_modules/babel-core/lib/transformation/file/options/option-manager.js:293:19
at Array.map ()
at OptionManager.resolvePresets (/srv/http/productionboard/node_modules/babel-core/lib/transformation/file/options/option-manager.js:275:20)
at OptionManager.mergePresets (/srv/http/productionboard/node_modules/babel-core/lib/transformation/file/options/option-manager.js:264:10)
at OptionManager.mergeOptions (/srv/http/productionboard/node_modules/babel-core/lib/transformation/file/options/option-manager.js:249:14)
at OptionManager.init (/srv/http/productionboard/node_modules/babel-core/lib/transformation/file/options/option-manager.js:368:12)
at File.initOptions (/srv/http/productionboard/node_modules/babel-core/lib/transformation/file/index.js:212:65)
at new File (/srv/http/productionboard/node_modules/babel-core/lib/transformation/file/index.js:135:24)
at Pipeline.transform (/srv/http/productionboard/node_modules/babel-core/lib/transformation/pipeline.js:46:16)
at transpile (/srv/http/productionboard/node_modules/babel-loader/lib/index.js:50:20)
at /srv/http/productionboard/node_modules/babel-loader/lib/fs-cache.js:118:18
at ReadFileContext.callback (/srv/http/productionboard/node_modules/babel-loader/lib/fs-cache.js:31:21)
at FSReqWrap.readFileAfterOpen [as oncomplete] (fs.js:235:13)
@ ./node_modules/vue-kanban/src/components/Kanban.vue 4:21-346
@ ./node_modules/vue-kanban/src/plugin.js
@ ./resources/js/app.js
@ multi ./resources/js/app.js ./resources/sass/app.scss

Order by

I noticed that they are ordered by "id"
Isn't possible to order them by a variable that I set, such as value?

Stages from array of objects instead of strings

Is it possible to render the board with the stages made of an array of objects instead of an array of strings?

I mean, something like this:

stages: [{
  name: "Stage 1",
  id: 1
}, {
  name: "Stage 2",
  id: 2
}, {
  name: "Stage 3",
  id: 3
}]

Instead of:

stages: ["Stage 1", "Stage 2", "Stage 3"]

My structure is the following:

<kanban-board :stages="stages" :blocks="blocks">
    <div v-for="stage in stages" :slot="stage">
        <h2>{{ stage.name }}</h2>
    </div>
    <el-card v-for="block in blocks" :slot="block.id">
        <div><strong>id:</strong>{{ block.id }}</div>
        <div>{{ block.title }}</div>
    </el-card>
</kanban-board>

This is the result:
image

https://screencast.com/t/NTcrSUWqe
Thanks!

Build error - Can't resolve './components/Kanban'

Hello,

With Webpack 3.7, I have the following build error:

ERROR in ./node_modules/vue-kanban/src/plugin.js
Module not found: Error: Can't resolve './components/Kanban'

I managed to fix the issue by changing the first line of src/plugin.js from

import Kanban from './components/Kanban';

to

import Kanban from './components/Kanban.vue';

Could you please push the change and tag a new version? If you want I can create a pull request with the changes.

Thank you :)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.