mirror of
https://github.com/amark/gun.git
synced 2025-03-30 15:08:33 +00:00
164 lines
4.0 KiB
HTML
164 lines
4.0 KiB
HTML
<!doctype html>
|
|
<html>
|
|
|
|
<head>
|
|
<title>Todo App: Gun + Vue</title>
|
|
|
|
<script src="https://unpkg.com/vue" type="text/javascript" charset="utf-8"></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/gun/gun.js" type="text/javascript" charset="utf-8"></script>
|
|
<link href='https://fonts.googleapis.com/css?family=Alegreya+Sans:300italic' rel='stylesheet' type='text/css'>
|
|
<style>
|
|
|
|
body,
|
|
html {
|
|
width: 100%;
|
|
font-family: 'Alegreya Sans', sans-serif;
|
|
}
|
|
|
|
body {
|
|
font-size: 20px;
|
|
background-color: rgba(0,0,0,.3);
|
|
}
|
|
|
|
h1,
|
|
h3,
|
|
h5 {
|
|
text-transform: uppercase;
|
|
font-weight: 600;
|
|
}
|
|
|
|
#app {
|
|
margin: 0 auto;
|
|
background-color: #fff;
|
|
max-width: 500px;
|
|
padding: 2em;
|
|
}
|
|
|
|
.add-todo {
|
|
font-size: 1em;
|
|
border: 1px solid black;
|
|
padding: .5em .25em;
|
|
}
|
|
|
|
.completed-header,
|
|
.completed,
|
|
.completed-time {
|
|
color: rgba(0,0,0,.3);
|
|
}
|
|
|
|
.completed {
|
|
text-decoration: line-through;
|
|
}
|
|
|
|
.completed-time {
|
|
font-size: .8em;
|
|
}
|
|
</style>
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<div id="app">
|
|
|
|
<div class="todo-wrapper">
|
|
<h1>Todos App</h1>
|
|
|
|
<input class="add-todo" type="text" placeholder="Add new todo" v-model="newTodo" @keyup.enter="addTodo">
|
|
|
|
<h3>Active</h3>
|
|
|
|
<div v-for="active in activeTodos">
|
|
<label><input type="checkbox" @click.prevent="completeTodo(active.key)"> {{ active.todo.description }}</label>
|
|
</div>
|
|
|
|
<h5 v-show="completedTodos.length > 0" class="completed-header">Completed</h5>
|
|
|
|
<div v-for="completed in completedTodos" @click="reopenTodo(completed.key)">
|
|
<span class="completed">{{ completed.todo.description }}</span>
|
|
<span class="completed-time">(completed at {{ (new Date(completed.todo.completed)).toUTCString() }})</span>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</body>
|
|
|
|
<script>
|
|
|
|
// Clear out local storage so we can start fresh each time.
|
|
localStorage.clear();
|
|
|
|
|
|
// No peers for the sake of example,
|
|
// but this could easily be a collaborative
|
|
// todolist by adding a few peers
|
|
var gun = new Gun();
|
|
var todos = gun.get('todos');
|
|
|
|
new Vue({
|
|
data: {
|
|
todos: [],
|
|
newTodo: ""
|
|
},
|
|
computed: {
|
|
activeTodos: function() {
|
|
return this.todos.filter(function(todo) {
|
|
return todo.todo.completed === '';
|
|
});
|
|
},
|
|
completedTodos: function() {
|
|
return this.todos.filter(function(todo) {
|
|
return todo.todo.completed !== '';
|
|
});
|
|
}
|
|
},
|
|
methods: {
|
|
todoUpdated: function(todo, nodeKey) {
|
|
if (/\D/.test(nodeKey)) {
|
|
return;
|
|
}
|
|
|
|
var existingTodoIndex = this.todos.findIndex(function(todo) {
|
|
return todo.key === nodeKey
|
|
});
|
|
var todoToStore = {
|
|
todo: todo,
|
|
key: nodeKey
|
|
};
|
|
if (existingTodoIndex === -1) {
|
|
this.todos.push(todoToStore);
|
|
} else {
|
|
this.todos.splice(existingTodoIndex, 1, todoToStore);
|
|
}
|
|
},
|
|
addTodo: function() {
|
|
var newTodo = todos.get(Date.now().toString());
|
|
newTodo.put({
|
|
description: this.newTodo,
|
|
completed: ''
|
|
});
|
|
todos.set(newTodo);
|
|
this.newTodo = "";
|
|
},
|
|
completeTodo: function(key) {
|
|
todos.get(key).put({
|
|
completed: Date.now()
|
|
});
|
|
},
|
|
reopenTodo: function(key) {
|
|
todos.get(key).put({
|
|
completed: ''
|
|
});
|
|
}
|
|
},
|
|
mounted: function() {
|
|
|
|
// Subscribe to updates on the todos set
|
|
todos.map().on(this.todoUpdated.bind(this));
|
|
}
|
|
}).$mount('#app');
|
|
|
|
</script>
|
|
|
|
</html>
|