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});4041window.addEventListener('beforeunload', () => {42 client.deactivate({ keepalive: true });43});4445const doc = new yorkie.Document(46 `vuejs-kanban-${new Date().toISOString().substring(0, 10).replace(/-/g, '')}`,47 { enableDevtools: true },48);4950export default {51 data() {52 return {53 lists: [],54 title: '',55 opened: null,56 };57 },58 created() {59 this.fetchDoc();60 },61 beforeUnmount() {62 this.disconnect();63 },64 watch: {65 opened(index) {66 this.$nextTick(function () {67 if (index === 0) {68 // Open add list form69 this.$refs['addListForm'].querySelector('input').focus();70 } else if (index) {71 // Or open add card form72 this.$refs['addCardForm'][index - 1].querySelector('input').focus();73 }74 this.title = '';75 });76 },77 },78 methods: {79 async fetchDoc() {80 await client.activate();81 await client.attach(doc);8283 doc.update((root) => {84 if (!root.lists) {85 root.lists = defaultLists;86 }87 }, 'create default list if not exists');8889 doc.subscribe((event) => {90 this.lists = doc.getRoot().lists;91 });92 await client.sync();9394 this.lists = doc.getRoot().lists;95 },9697 async disconnect() {98 await client.deactivate({ keepalive: true });99 },100101 isOpened(index) {102 return this.opened === index;103 },104105 openForm(index) {106 this.opened = index;107 },108109 closeForm() {110 this.opened = null;111 },112113 addCard(list) {114 if (this.title === '') return;115116 doc.update((root) => {117 root.lists.getElementByID(list.getID()).cards.push({118 title: this.title,119 });120 this.title = '';121 }, `add new card by ${client.getID()}`);122 },123124 deleteCard(list, card) {125 doc.update((root) => {126 root.lists.getElementByID(list.getID()).cards.deleteByID(card.getID());127 }, `delete a card by ${client.getID()}`);128 },129130 addList() {131 if (this.title === '') return;132133 doc.update((root) => {134 root.lists.push({135 title: this.title,136 cards: [],137 });138 this.title = '';139 }, `add new list by ${client.getID()}`);140 },141142 deleteList(list) {143 doc.update((root) => {144 root.lists.deleteByID(list.getID());145 }, `delete a list by ${client.getID()}`);146 },147 },148};149</script>150151<template>152 <div v-cloak class="list" v-for="(list, index) in lists">153 <span class="delete" v-on:click="deleteList(list)">❌</span>154 <div class="title">{{ list.title }}</div>155 <div class="card" v-for="card in list.cards">156 <span class="delete" v-on:click="deleteCard(list, card)">❌</span>157 {{ card.title }}158 </div>159 <div class="add-card" ref="addCardForm">160 <div v-if="isOpened(index + 1)" class="add-form">161 <input162 type="text"163 placeholder="Enter card title"164 v-model="title"165 v-on:keyup.enter="addCard(list)"166 v-on:keyup.esc="closeForm()"167 />168 <div class="buttons">169 <input type="button" value="Add" v-on:click="addCard(list)" />170 <input171 type="button"172 value="Close"173 class="pull-right"174 v-on:click="closeForm()"175 />176 </div>177 </div>178 <div v-else class="add-card-opener" v-on:click="openForm(index + 1)">179 Add another card180 </div>181 </div>182 </div>183 <div class="add-list" ref="addListForm">184 <div v-if="isOpened(0)" class="add-form">185 <input186 type="text"187 placeholder="Enter list title"188 v-model="title"189 v-on:keyup.enter="addList()"190 v-on:keyup.esc="closeForm()"191 />192 <div class="buttons">193 <input type="button" value="Add" v-on:click="addList()" />194 <input195 type="button"196 value="Close"197 class="pull-right"198 v-on:click="closeForm()"199 />200 </div>201 </div>202 <div v-else class="add-list-opener" v-on:click="openForm(0)">203 Add another list204 </div>205 </div>206</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