Kanban Board
Kanban Board is a tool for managing tasks and workflow. It is a visual way to manage tasks and workflow.
App.vue
1<script>2import yorkie from 'yorkie-js-sdk';34const defaultLists = [5 {6 title: 'Todo',7 cards: [8 {9 title: 'Pruning document',10 },11 {12 title: 'Clean up codes'13 }14 ]15 },16 {17 title: 'Doing',18 cards: [19 {20 title: 'Array operations',21 }22 ]23 },24 {25 title: 'Done',26 cards: [27 {28 title: 'Create a sample page',29 },30 {31 title: 'Launch demo site'32 }33 ]34 },35];3637const client = new yorkie.Client(import.meta.env.VITE_YORKIE_API_ADDR, {38 apiKey: import.meta.env.VITE_YORKIE_API_KEY,39});40const doc = new yorkie.Document('vuejs-kanban');4142export default {43 data() {44 return {45 lists: [],46 title: '',47 opened: null,48 };49 },50 created() {51 this.fetchDoc();52 },53 watch: {54 opened(index) {55 this.$nextTick(function () {56 if (index === 0) {57 // Open add list form58 this.$refs['addListForm'].querySelector('input').focus();59 } else {60 // Or open add card form61 this.$refs['addCardForm'][index - 1].querySelector('input').focus();62 }63 });64 },65 },66 methods: {67 async fetchDoc() {68 await client.activate();69 await client.attach(doc);707172 doc.update((root) => {73 if (!root.lists) {74 root.lists = defaultLists;75 }76 }, 'create default list if not exists');7778 doc.subscribe((event) => {79 this.lists = doc.getRoot().lists;80 });81 await client.sync();8283 this.lists = doc.getRoot().lists;84 },8586 isOpened(index) {87 return this.opened === index;88 },8990 openForm(index) {91 this.opened = index;92 },9394 closeForm() {95 this.opened = null;96 },9798 addCard(list) {99 if (this.title === '') return;100101 doc.update((root) => {102 root.lists.getElementByID(list.getID()).cards.push({103 title: this.title,104 });105 this.title = '';106 }, `add new card by ${client.getID()}`);107 },108109 deleteCard(list, card) {110 doc.update((root) => {111 root.lists.getElementByID(list.getID()).cards.deleteByID(card.getID());112 }, `delete a card by ${client.getID()}`);113 },114115 addList() {116 if (this.title === '') return;117118 doc.update((root) => {119 root.lists.push({120 title: this.title,121 cards: [],122 });123 this.title = '';124 }, `add new list by ${client.getID()}`);125 },126127 deleteList(list) {128 doc.update((root) => {129 root.lists.deleteByID(list.getID());130 }, `delete a list by ${client.getID()}`);131 },132 },133}134</script>135136<template>137 <div v-cloak class="list" v-for="(list, index) in lists">138 <span class="delete" v-on:click="deleteList(list)">❌</span>139 <div class="title">{{ list.title }}</div>140 <div class="card" v-for="card in list.cards">141 <span class="delete" v-on:click="deleteCard(list, card)">❌</span>142 {{ card.title }}143 </div>144 <div class="add-card" ref="addCardForm">145 <div v-if="isOpened(index + 1)" class="add-form">146 <input type="text" placeholder="Enter card title" v-model="title" v-on:keyup.enter="addCard(list)"147 v-on:keyup.esc="closeForm()">148 <div class="buttons">149 <input type="button" value="Add" v-on:click="addCard(list)">150 <input type="button" value="Close" class="pull-right" v-on:click="closeForm()">151 </div>152 </div>153 <div v-else class="add-card-opener" v-on:click="openForm(index + 1)">Add another card</div>154 </div>155 </div>156 <div class="add-list" ref="addListForm">157 <div v-if="isOpened(0)" class="add-form">158 <input type="text" placeholder="Enter list title" v-model="title" v-on:keyup.enter="addList()"159 v-on:keyup.esc="closeForm()">160 <div class="buttons">161 <input type="button" value="Add" v-on:click="addList()">162 <input type="button" value="Close" class="pull-right" v-on:click="closeForm()">163 </div>164 </div>165 <div v-else class="add-list-opener" v-on:click="openForm(0)">Add another list</div>166 </div>167</template>
export type KanbanDoc = {lists: Array<List>;};export type List = {title: string;cards: Array<Card>;};export type Card = {title: string;};
- User 1
- User 2
- User 1
- User 2
Event Log