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(41 `vuejs-kanban-${new Date().toISOString().substring(0, 10).replace(/-/g, '')}`,42 { enableDevtools: true },43);4445export default {46 data() {47 return {48 lists: [],49 title: '',50 opened: null,51 };52 },53 created() {54 this.fetchDoc();55 },56 beforeUnmount() {57 this.disconnect();58 },59 watch: {60 opened(index) {61 this.$nextTick(function () {62 if (index === 0) {63 // Open add list form64 this.$refs['addListForm'].querySelector('input').focus();65 } else if (index) {66 // Or open add card form67 this.$refs['addCardForm'][index - 1].querySelector('input').focus();68 }69 this.title = '';70 });71 },72 },73 methods: {74 async fetchDoc() {75 await client.activate();76 await client.attach(doc);7778 doc.update((root) => {79 if (!root.lists) {80 root.lists = defaultLists;81 }82 }, 'create default list if not exists');8384 doc.subscribe((event) => {85 this.lists = doc.getRoot().lists;86 });87 await client.sync();8889 this.lists = doc.getRoot().lists;90 },9192 async disconnect() {93 await client.deactivate();94 },9596 isOpened(index) {97 return this.opened === index;98 },99100 openForm(index) {101 this.opened = index;102 },103104 closeForm() {105 this.opened = null;106 },107108 addCard(list) {109 if (this.title === '') return;110111 doc.update((root) => {112 root.lists.getElementByID(list.getID()).cards.push({113 title: this.title,114 });115 this.title = '';116 }, `add new card by ${client.getID()}`);117 },118119 deleteCard(list, card) {120 doc.update((root) => {121 root.lists.getElementByID(list.getID()).cards.deleteByID(card.getID());122 }, `delete a card by ${client.getID()}`);123 },124125 addList() {126 if (this.title === '') return;127128 doc.update((root) => {129 root.lists.push({130 title: this.title,131 cards: [],132 });133 this.title = '';134 }, `add new list by ${client.getID()}`);135 },136137 deleteList(list) {138 doc.update((root) => {139 root.lists.deleteByID(list.getID());140 }, `delete a list by ${client.getID()}`);141 },142 },143};144</script>145146<template>147 <div v-cloak class="list" v-for="(list, index) in lists">148 <span class="delete" v-on:click="deleteList(list)">❌</span>149 <div class="title">{{ list.title }}</div>150 <div class="card" v-for="card in list.cards">151 <span class="delete" v-on:click="deleteCard(list, card)">❌</span>152 {{ card.title }}153 </div>154 <div class="add-card" ref="addCardForm">155 <div v-if="isOpened(index + 1)" class="add-form">156 <input157 type="text"158 placeholder="Enter card title"159 v-model="title"160 v-on:keyup.enter="addCard(list)"161 v-on:keyup.esc="closeForm()"162 />163 <div class="buttons">164 <input type="button" value="Add" v-on:click="addCard(list)" />165 <input166 type="button"167 value="Close"168 class="pull-right"169 v-on:click="closeForm()"170 />171 </div>172 </div>173 <div v-else class="add-card-opener" v-on:click="openForm(index + 1)">174 Add another card175 </div>176 </div>177 </div>178 <div class="add-list" ref="addListForm">179 <div v-if="isOpened(0)" class="add-form">180 <input181 type="text"182 placeholder="Enter list title"183 v-model="title"184 v-on:keyup.enter="addList()"185 v-on:keyup.esc="closeForm()"186 />187 <div class="buttons">188 <input type="button" value="Add" v-on:click="addList()" />189 <input190 type="button"191 value="Close"192 class="pull-right"193 v-on:click="closeForm()"194 />195 </div>196 </div>197 <div v-else class="add-list-opener" v-on:click="openForm(0)">198 Add another list199 </div>200 </div>201</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